1 package com.atlassian.util.concurrent;
2
3 import static com.atlassian.util.concurrent.Functions.fromSupplier;
4 import static com.atlassian.util.concurrent.LockManagers.Manager.createManager;
5 import static com.atlassian.util.concurrent.ManagedLocks.lockFactory;
6 import static com.atlassian.util.concurrent.ManagedLocks.managedLockFactory;
7 import static com.atlassian.util.concurrent.WeakMemoizer.weakMemoizer;
8
9 import java.util.concurrent.Callable;
10 import java.util.concurrent.locks.Lock;
11
12 /**
13 * @deprecated since 0.0.7 use {@link ManagedLocks} instead
14 */
15 @Deprecated
16 // /CLOVER:OFF
17 public class LockManagers {
18
19 /**
20 * Convenience method that simply calls
21 * {@link ManagedLocks#weakLockManager(Function)} with the identity
22 * function. So all inputs map directly to an individual lock.
23 *
24 * @param <T> the type of the thing used to look up locks
25 * @param <D> the type used to map lock instances
26 * @param stripeFunction to convert Ts to Ds.
27 * @see ManagedLocks#weakLockManager(Function, int)
28 * @deprecated use {@link #weakManagedLockFactory()} instead.
29 */
30 @Deprecated
31 public static <T> LockManager<T> weakLockManager() {
32 return weakLockManager(Functions.<T> identity());
33 }
34
35 /**
36 * Get a {@link LockManager} that is used to perform operations under a
37 * particular lock. The specific lock chosen is decided by the supplied
38 * striping function. The particular {@link Lock} is resolved using a
39 * {@link Function} that resolves to a descriptor used to look up a Lock
40 * instance. This allows for a finite set of locks to be used even if the
41 * set of T is essentially unbounded.
42 * <p>
43 * For instance:
44 *
45 * <pre>
46 * LockManager<Identifiable, Integer> manager = LockManagers.weakLockManager(new Function<Identifiable, Integer>() {
47 * Integer get(Identifiable thing) {
48 * return thing.getId() % 16;
49 * }
50 * };
51 * </pre>
52 *
53 * uses only 16 possible locks as the function returns the modulo 16 of the
54 * thing's id.
55 *
56 * @param <T> the type of the thing used to look up locks
57 * @param <D> the type used to map lock instances
58 * @param stripeFunction to convert Ts to Ds.
59 * @param initialCapacity the initial capacity of the internal map.
60 * @return a new {@link LockManager} instance that stores created
61 * {@link Lock} instances with weak references.
62 * @deprecated use {@link #weakManagedLockFactory(Function, int)} instead.
63 */
64 @Deprecated
65 public static <T, D> LockManager<T> weakLockManager(final Function<T, D> stripeFunction) {
66 final Function<D, ManagedLock> lockFactory = fromSupplier(managedLockFactory(lockFactory()));
67 final WeakMemoizer<D, ManagedLock> memoizer = weakMemoizer(lockFactory);
68 return createManager(memoizer, stripeFunction);
69 }
70
71 /**
72 * Default implementation of {@link LockManager}
73 *
74 * @param <T> the input type
75 * @param <D> the type used for the internal lock resolution.
76 */
77 static class Manager<T, D> implements LockManager<T> {
78 static final <T, D> Manager<T, D> createManager(final Function<D, ManagedLock> lockFactory, final Function<T, D> stripeFunction) {
79 return new Manager<T, D>(lockFactory, stripeFunction);
80 }
81
82 private final Function<D, ManagedLock> lockFactory;
83 private final Function<T, D> stripeFunction;
84
85 Manager(final Function<D, ManagedLock> lockFactory, final Function<T, D> stripeFunction) {
86 this.lockFactory = lockFactory;
87 this.stripeFunction = stripeFunction;
88 }
89
90 public <R> R withLock(final T descriptor, final Supplier<R> supplier) {
91 return lockFactory.get(stripeFunction.get(descriptor)).withLock(supplier);
92 }
93
94 public <R> R withLock(final T descriptor, final Callable<R> callable) throws Exception {
95 return lockFactory.get(stripeFunction.get(descriptor)).withLock(callable);
96 }
97
98 public void withLock(final T descriptor, final Runnable runnable) {
99 lockFactory.get(stripeFunction.get(descriptor)).withLock(runnable);
100 }
101 }
102 }
103 // /CLOVER:ON