/** * Create a {@link Function} for resolving {@link ManagedLock.ReadWrite * managed read-write locks}. The particular lock is resolved using a striping * {@link Function} that is used look up a lock instance. This allows for a * finite set of locks to be used even if the set of T is essentially * unbounded. The locks are stored using weak references so infrequently * accessed locks should not use excess memory. * * @param <T> the type of the thing used to look up locks * @param <D> the type used to map lock instances, should be a good map key * @param stripeFunction to convert the input to the thing used to look up the * individual locks * @param lockFactory the factory for creating the individual locks * @return a new {@link Function} that provides {@link ManagedLock.ReadWrite} * instances that stores created instances with weak references. */ public static @NotNull <T, D> com.atlassian.util.concurrent.Function<T, ManagedLock.ReadWrite> weakReadWriteManagedLockFactory( final @NotNull Function<T, D> stripeFunction, final @NotNull Supplier<ReadWriteLock> lockFactory) { notNull("stripeFunction", stripeFunction); final Function<D, ReadWrite> readWriteManagedLockFactory = fromSupplier(managedReadWriteLockFactory(lockFactory)); final WeakMemoizer<D, ManagedLock.ReadWrite> locks = weakMemoizer(readWriteManagedLockFactory); return new Function<T, ManagedLock.ReadWrite>() { public ManagedLock.ReadWrite get(final T input) { return locks.get(stripeFunction.get(input)); }; }; }