1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package info.magnolia.cache.concurrent;
17
18 import java.util.concurrent.ExecutorService;
19 import java.util.concurrent.TimeUnit;
20
21 import net.spy.memcached.OperationTimeoutException;
22
23
24
25
26
27
28
29 public final class ConcurrencyUtil {
30
31 private static final int DOUG_LEA_BLACK_MAGIC_OPERAND_1 = 20;
32 private static final int DOUG_LEA_BLACK_MAGIC_OPERAND_2 = 12;
33 private static final int DOUG_LEA_BLACK_MAGIC_OPERAND_3 = 7;
34 private static final int DOUG_LEA_BLACK_MAGIC_OPERAND_4 = 4;
35
36
37
38
39
40 private ConcurrencyUtil() {
41
42 }
43
44
45
46
47
48
49
50
51
52
53
54 public static int hash(Object object) {
55 int h = object.hashCode();
56 h ^= (h >>> DOUG_LEA_BLACK_MAGIC_OPERAND_1) ^ (h >>> DOUG_LEA_BLACK_MAGIC_OPERAND_2);
57 return h ^ (h >>> DOUG_LEA_BLACK_MAGIC_OPERAND_3) ^ (h >>> DOUG_LEA_BLACK_MAGIC_OPERAND_4);
58 }
59
60
61
62
63
64
65
66 public static int selectLock(final Object key, int numberOfLocks) {
67 int number = numberOfLocks & (numberOfLocks - 1);
68 if (number != 0) {
69 throw new IllegalStateException("Lock number must be a power of two: " + numberOfLocks);
70 }
71 if (key == null) {
72 return 0;
73 } else {
74 int hash = hash(key) & (numberOfLocks - 1);
75 return hash;
76 }
77
78 }
79
80
81
82
83
84
85
86
87
88
89 public static void shutdownAndWaitForTermination(ExecutorService pool, int waitSeconds) throws OperationTimeoutException {
90
91 pool.shutdown();
92 try {
93
94 if (!pool.awaitTermination(waitSeconds, TimeUnit.SECONDS)) {
95
96 pool.shutdownNow();
97
98 if (!pool.awaitTermination(waitSeconds, TimeUnit.SECONDS)) {
99
100 throw new OperationTimeoutException("Pool did not terminate");
101 }
102 }
103 } catch (InterruptedException ie) {
104
105 pool.shutdownNow();
106 Thread.currentThread().interrupt();
107 }
108 }
109 }