concurrent-ruby 1.0.5 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +65 -0
  3. data/Gemfile +39 -0
  4. data/{LICENSE.txt → LICENSE.md} +2 -0
  5. data/README.md +207 -105
  6. data/Rakefile +314 -0
  7. data/ext/concurrent-ruby/ConcurrentRubyService.java +17 -0
  8. data/ext/concurrent-ruby/com/concurrent_ruby/ext/AtomicReferenceLibrary.java +175 -0
  9. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java +248 -0
  10. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicBooleanLibrary.java +93 -0
  11. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +113 -0
  12. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +159 -0
  13. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +306 -0
  14. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMap.java +31 -0
  15. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +3863 -0
  16. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/LongAdder.java +203 -0
  17. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/Striped64.java +342 -0
  18. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +3800 -0
  19. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/LongAdder.java +204 -0
  20. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/Striped64.java +291 -0
  21. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166y/ThreadLocalRandom.java +199 -0
  22. data/lib/concurrent/agent.rb +7 -7
  23. data/lib/concurrent/array.rb +59 -32
  24. data/lib/concurrent/async.rb +4 -4
  25. data/lib/concurrent/atom.rb +9 -9
  26. data/lib/concurrent/atomic/atomic_boolean.rb +24 -20
  27. data/lib/concurrent/atomic/atomic_fixnum.rb +27 -23
  28. data/lib/concurrent/atomic/atomic_markable_reference.rb +164 -0
  29. data/lib/concurrent/atomic/atomic_reference.rb +185 -32
  30. data/lib/concurrent/atomic/count_down_latch.rb +6 -6
  31. data/lib/concurrent/atomic/cyclic_barrier.rb +1 -1
  32. data/lib/concurrent/atomic/event.rb +1 -1
  33. data/lib/concurrent/atomic/java_count_down_latch.rb +9 -6
  34. data/lib/concurrent/atomic/mutex_atomic_boolean.rb +2 -0
  35. data/lib/concurrent/atomic/mutex_count_down_latch.rb +1 -0
  36. data/lib/concurrent/atomic/read_write_lock.rb +2 -1
  37. data/lib/concurrent/atomic/reentrant_read_write_lock.rb +3 -1
  38. data/lib/concurrent/atomic/semaphore.rb +8 -8
  39. data/lib/concurrent/atomic/thread_local_var.rb +7 -7
  40. data/lib/concurrent/atomic_reference/mutex_atomic.rb +3 -8
  41. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +1 -1
  42. data/lib/concurrent/atomics.rb +0 -43
  43. data/lib/concurrent/collection/lock_free_stack.rb +158 -0
  44. data/lib/concurrent/collection/map/atomic_reference_map_backend.rb +3 -3
  45. data/lib/concurrent/collection/map/non_concurrent_map_backend.rb +1 -2
  46. data/lib/concurrent/collection/non_concurrent_priority_queue.rb +29 -29
  47. data/lib/concurrent/concern/dereferenceable.rb +1 -1
  48. data/lib/concurrent/concern/logging.rb +6 -1
  49. data/lib/concurrent/concern/observable.rb +7 -7
  50. data/lib/concurrent/concurrent_ruby.jar +0 -0
  51. data/lib/concurrent/configuration.rb +1 -6
  52. data/lib/concurrent/constants.rb +1 -1
  53. data/lib/concurrent/dataflow.rb +2 -1
  54. data/lib/concurrent/delay.rb +9 -7
  55. data/lib/concurrent/exchanger.rb +21 -25
  56. data/lib/concurrent/executor/abstract_executor_service.rb +2 -2
  57. data/lib/concurrent/executor/cached_thread_pool.rb +1 -1
  58. data/lib/concurrent/executor/executor_service.rb +15 -15
  59. data/lib/concurrent/executor/fixed_thread_pool.rb +18 -18
  60. data/lib/concurrent/executor/java_thread_pool_executor.rb +10 -7
  61. data/lib/concurrent/executor/single_thread_executor.rb +2 -2
  62. data/lib/concurrent/executor/thread_pool_executor.rb +6 -6
  63. data/lib/concurrent/executor/timer_set.rb +1 -1
  64. data/lib/concurrent/future.rb +4 -1
  65. data/lib/concurrent/hash.rb +53 -30
  66. data/lib/concurrent/ivar.rb +5 -6
  67. data/lib/concurrent/map.rb +178 -81
  68. data/lib/concurrent/maybe.rb +1 -1
  69. data/lib/concurrent/mutable_struct.rb +15 -14
  70. data/lib/concurrent/mvar.rb +2 -2
  71. data/lib/concurrent/promise.rb +53 -21
  72. data/lib/concurrent/promises.rb +1936 -0
  73. data/lib/concurrent/re_include.rb +58 -0
  74. data/lib/concurrent/set.rb +66 -0
  75. data/lib/concurrent/settable_struct.rb +1 -0
  76. data/lib/concurrent/synchronization/abstract_lockable_object.rb +5 -5
  77. data/lib/concurrent/synchronization/abstract_struct.rb +6 -4
  78. data/lib/concurrent/synchronization/lockable_object.rb +6 -6
  79. data/lib/concurrent/synchronization/{mri_lockable_object.rb → mutex_lockable_object.rb} +19 -14
  80. data/lib/concurrent/synchronization/object.rb +8 -4
  81. data/lib/concurrent/synchronization/truffleruby_object.rb +46 -0
  82. data/lib/concurrent/synchronization/volatile.rb +11 -9
  83. data/lib/concurrent/synchronization.rb +4 -5
  84. data/lib/concurrent/thread_safe/util/data_structures.rb +63 -0
  85. data/lib/concurrent/thread_safe/util/striped64.rb +9 -4
  86. data/lib/concurrent/timer_task.rb +5 -2
  87. data/lib/concurrent/tuple.rb +1 -1
  88. data/lib/concurrent/tvar.rb +2 -2
  89. data/lib/concurrent/utility/193.rb +17 -0
  90. data/lib/concurrent/utility/at_exit.rb +1 -1
  91. data/lib/concurrent/utility/engine.rb +4 -4
  92. data/lib/concurrent/utility/monotonic_time.rb +3 -3
  93. data/lib/concurrent/utility/native_extension_loader.rb +31 -33
  94. data/lib/concurrent/utility/processor_counter.rb +0 -2
  95. data/lib/concurrent/version.rb +2 -2
  96. data/lib/concurrent-ruby.rb +1 -0
  97. data/lib/concurrent.rb +26 -20
  98. metadata +33 -18
  99. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +0 -8
  100. data/lib/concurrent/atomic_reference/direct_update.rb +0 -81
  101. data/lib/concurrent/atomic_reference/jruby+truffle.rb +0 -2
  102. data/lib/concurrent/atomic_reference/jruby.rb +0 -16
  103. data/lib/concurrent/atomic_reference/rbx.rb +0 -22
  104. data/lib/concurrent/atomic_reference/ruby.rb +0 -32
  105. data/lib/concurrent/edge.rb +0 -26
  106. data/lib/concurrent/lazy_register.rb +0 -81
  107. data/lib/concurrent/synchronization/truffle_lockable_object.rb +0 -9
  108. data/lib/concurrent/synchronization/truffle_object.rb +0 -31
  109. data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +0 -30
@@ -0,0 +1,203 @@
1
+ /*
2
+ * Written by Doug Lea with assistance from members of JCP JSR-166
3
+ * Expert Group and released to the public domain, as explained at
4
+ * http://creativecommons.org/publicdomain/zero/1.0/
5
+ */
6
+
7
+ // This is based on 1.9 version.
8
+
9
+ package com.concurrent_ruby.ext.jsr166e;
10
+ import java.util.concurrent.atomic.AtomicLong;
11
+ import java.io.IOException;
12
+ import java.io.Serializable;
13
+ import java.io.ObjectInputStream;
14
+
15
+ /**
16
+ * One or more variables that together maintain an initially zero
17
+ * {@code long} sum. When updates (method {@link #add}) are contended
18
+ * across threads, the set of variables may grow dynamically to reduce
19
+ * contention. Method {@link #sum} (or, equivalently, {@link
20
+ * #longValue}) returns the current total combined across the
21
+ * variables maintaining the sum.
22
+ *
23
+ * <p>This class is usually preferable to {@link AtomicLong} when
24
+ * multiple threads update a common sum that is used for purposes such
25
+ * as collecting statistics, not for fine-grained synchronization
26
+ * control. Under low update contention, the two classes have similar
27
+ * characteristics. But under high contention, expected throughput of
28
+ * this class is significantly higher, at the expense of higher space
29
+ * consumption.
30
+ *
31
+ * <p>This class extends {@link Number}, but does <em>not</em> define
32
+ * methods such as {@code hashCode} and {@code compareTo} because
33
+ * instances are expected to be mutated, and so are not useful as
34
+ * collection keys.
35
+ *
36
+ * <p><em>jsr166e note: This class is targeted to be placed in
37
+ * java.util.concurrent.atomic.</em>
38
+ *
39
+ * @since 1.8
40
+ * @author Doug Lea
41
+ */
42
+ public class LongAdder extends Striped64 implements Serializable {
43
+ private static final long serialVersionUID = 7249069246863182397L;
44
+
45
+ /**
46
+ * Version of plus for use in retryUpdate
47
+ */
48
+ final long fn(long v, long x) { return v + x; }
49
+
50
+ /**
51
+ * Creates a new adder with initial sum of zero.
52
+ */
53
+ public LongAdder() {
54
+ }
55
+
56
+ /**
57
+ * Adds the given value.
58
+ *
59
+ * @param x the value to add
60
+ */
61
+ public void add(long x) {
62
+ Cell[] as; long b, v; HashCode hc; Cell a; int n;
63
+ if ((as = cells) != null || !casBase(b = base, b + x)) {
64
+ boolean uncontended = true;
65
+ int h = (hc = threadHashCode.get()).code;
66
+ if (as == null || (n = as.length) < 1 ||
67
+ (a = as[(n - 1) & h]) == null ||
68
+ !(uncontended = a.cas(v = a.value, v + x)))
69
+ retryUpdate(x, hc, uncontended);
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Equivalent to {@code add(1)}.
75
+ */
76
+ public void increment() {
77
+ add(1L);
78
+ }
79
+
80
+ /**
81
+ * Equivalent to {@code add(-1)}.
82
+ */
83
+ public void decrement() {
84
+ add(-1L);
85
+ }
86
+
87
+ /**
88
+ * Returns the current sum. The returned value is <em>NOT</em> an
89
+ * atomic snapshot: Invocation in the absence of concurrent
90
+ * updates returns an accurate result, but concurrent updates that
91
+ * occur while the sum is being calculated might not be
92
+ * incorporated.
93
+ *
94
+ * @return the sum
95
+ */
96
+ public long sum() {
97
+ long sum = base;
98
+ Cell[] as = cells;
99
+ if (as != null) {
100
+ int n = as.length;
101
+ for (int i = 0; i < n; ++i) {
102
+ Cell a = as[i];
103
+ if (a != null)
104
+ sum += a.value;
105
+ }
106
+ }
107
+ return sum;
108
+ }
109
+
110
+ /**
111
+ * Resets variables maintaining the sum to zero. This method may
112
+ * be a useful alternative to creating a new adder, but is only
113
+ * effective if there are no concurrent updates. Because this
114
+ * method is intrinsically racy, it should only be used when it is
115
+ * known that no threads are concurrently updating.
116
+ */
117
+ public void reset() {
118
+ internalReset(0L);
119
+ }
120
+
121
+ /**
122
+ * Equivalent in effect to {@link #sum} followed by {@link
123
+ * #reset}. This method may apply for example during quiescent
124
+ * points between multithreaded computations. If there are
125
+ * updates concurrent with this method, the returned value is
126
+ * <em>not</em> guaranteed to be the final value occurring before
127
+ * the reset.
128
+ *
129
+ * @return the sum
130
+ */
131
+ public long sumThenReset() {
132
+ long sum = base;
133
+ Cell[] as = cells;
134
+ base = 0L;
135
+ if (as != null) {
136
+ int n = as.length;
137
+ for (int i = 0; i < n; ++i) {
138
+ Cell a = as[i];
139
+ if (a != null) {
140
+ sum += a.value;
141
+ a.value = 0L;
142
+ }
143
+ }
144
+ }
145
+ return sum;
146
+ }
147
+
148
+ /**
149
+ * Returns the String representation of the {@link #sum}.
150
+ * @return the String representation of the {@link #sum}
151
+ */
152
+ public String toString() {
153
+ return Long.toString(sum());
154
+ }
155
+
156
+ /**
157
+ * Equivalent to {@link #sum}.
158
+ *
159
+ * @return the sum
160
+ */
161
+ public long longValue() {
162
+ return sum();
163
+ }
164
+
165
+ /**
166
+ * Returns the {@link #sum} as an {@code int} after a narrowing
167
+ * primitive conversion.
168
+ */
169
+ public int intValue() {
170
+ return (int)sum();
171
+ }
172
+
173
+ /**
174
+ * Returns the {@link #sum} as a {@code float}
175
+ * after a widening primitive conversion.
176
+ */
177
+ public float floatValue() {
178
+ return (float)sum();
179
+ }
180
+
181
+ /**
182
+ * Returns the {@link #sum} as a {@code double} after a widening
183
+ * primitive conversion.
184
+ */
185
+ public double doubleValue() {
186
+ return (double)sum();
187
+ }
188
+
189
+ private void writeObject(java.io.ObjectOutputStream s)
190
+ throws java.io.IOException {
191
+ s.defaultWriteObject();
192
+ s.writeLong(sum());
193
+ }
194
+
195
+ private void readObject(ObjectInputStream s)
196
+ throws IOException, ClassNotFoundException {
197
+ s.defaultReadObject();
198
+ busy = 0;
199
+ cells = null;
200
+ base = s.readLong();
201
+ }
202
+
203
+ }
@@ -0,0 +1,342 @@
1
+ /*
2
+ * Written by Doug Lea with assistance from members of JCP JSR-166
3
+ * Expert Group and released to the public domain, as explained at
4
+ * http://creativecommons.org/publicdomain/zero/1.0/
5
+ */
6
+
7
+ // This is based on 1.5 version.
8
+
9
+ package com.concurrent_ruby.ext.jsr166e;
10
+ import java.util.Random;
11
+
12
+ /**
13
+ * A package-local class holding common representation and mechanics
14
+ * for classes supporting dynamic striping on 64bit values. The class
15
+ * extends Number so that concrete subclasses must publicly do so.
16
+ */
17
+ abstract class Striped64 extends Number {
18
+ /*
19
+ * This class maintains a lazily-initialized table of atomically
20
+ * updated variables, plus an extra "base" field. The table size
21
+ * is a power of two. Indexing uses masked per-thread hash codes.
22
+ * Nearly all declarations in this class are package-private,
23
+ * accessed directly by subclasses.
24
+ *
25
+ * Table entries are of class Cell; a variant of AtomicLong padded
26
+ * to reduce cache contention on most processors. Padding is
27
+ * overkill for most Atomics because they are usually irregularly
28
+ * scattered in memory and thus don't interfere much with each
29
+ * other. But Atomic objects residing in arrays will tend to be
30
+ * placed adjacent to each other, and so will most often share
31
+ * cache lines (with a huge negative performance impact) without
32
+ * this precaution.
33
+ *
34
+ * In part because Cells are relatively large, we avoid creating
35
+ * them until they are needed. When there is no contention, all
36
+ * updates are made to the base field. Upon first contention (a
37
+ * failed CAS on base update), the table is initialized to size 2.
38
+ * The table size is doubled upon further contention until
39
+ * reaching the nearest power of two greater than or equal to the
40
+ * number of CPUS. Table slots remain empty (null) until they are
41
+ * needed.
42
+ *
43
+ * A single spinlock ("busy") is used for initializing and
44
+ * resizing the table, as well as populating slots with new Cells.
45
+ * There is no need for a blocking lock: When the lock is not
46
+ * available, threads try other slots (or the base). During these
47
+ * retries, there is increased contention and reduced locality,
48
+ * which is still better than alternatives.
49
+ *
50
+ * Per-thread hash codes are initialized to random values.
51
+ * Contention and/or table collisions are indicated by failed
52
+ * CASes when performing an update operation (see method
53
+ * retryUpdate). Upon a collision, if the table size is less than
54
+ * the capacity, it is doubled in size unless some other thread
55
+ * holds the lock. If a hashed slot is empty, and lock is
56
+ * available, a new Cell is created. Otherwise, if the slot
57
+ * exists, a CAS is tried. Retries proceed by "double hashing",
58
+ * using a secondary hash (Marsaglia XorShift) to try to find a
59
+ * free slot.
60
+ *
61
+ * The table size is capped because, when there are more threads
62
+ * than CPUs, supposing that each thread were bound to a CPU,
63
+ * there would exist a perfect hash function mapping threads to
64
+ * slots that eliminates collisions. When we reach capacity, we
65
+ * search for this mapping by randomly varying the hash codes of
66
+ * colliding threads. Because search is random, and collisions
67
+ * only become known via CAS failures, convergence can be slow,
68
+ * and because threads are typically not bound to CPUS forever,
69
+ * may not occur at all. However, despite these limitations,
70
+ * observed contention rates are typically low in these cases.
71
+ *
72
+ * It is possible for a Cell to become unused when threads that
73
+ * once hashed to it terminate, as well as in the case where
74
+ * doubling the table causes no thread to hash to it under
75
+ * expanded mask. We do not try to detect or remove such cells,
76
+ * under the assumption that for long-running instances, observed
77
+ * contention levels will recur, so the cells will eventually be
78
+ * needed again; and for short-lived ones, it does not matter.
79
+ */
80
+
81
+ /**
82
+ * Padded variant of AtomicLong supporting only raw accesses plus CAS.
83
+ * The value field is placed between pads, hoping that the JVM doesn't
84
+ * reorder them.
85
+ *
86
+ * JVM intrinsics note: It would be possible to use a release-only
87
+ * form of CAS here, if it were provided.
88
+ */
89
+ static final class Cell {
90
+ volatile long p0, p1, p2, p3, p4, p5, p6;
91
+ volatile long value;
92
+ volatile long q0, q1, q2, q3, q4, q5, q6;
93
+ Cell(long x) { value = x; }
94
+
95
+ final boolean cas(long cmp, long val) {
96
+ return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val);
97
+ }
98
+
99
+ // Unsafe mechanics
100
+ private static final sun.misc.Unsafe UNSAFE;
101
+ private static final long valueOffset;
102
+ static {
103
+ try {
104
+ UNSAFE = getUnsafe();
105
+ Class<?> ak = Cell.class;
106
+ valueOffset = UNSAFE.objectFieldOffset
107
+ (ak.getDeclaredField("value"));
108
+ } catch (Exception e) {
109
+ throw new Error(e);
110
+ }
111
+ }
112
+
113
+ }
114
+
115
+ /**
116
+ * Holder for the thread-local hash code. The code is initially
117
+ * random, but may be set to a different value upon collisions.
118
+ */
119
+ static final class HashCode {
120
+ static final Random rng = new Random();
121
+ int code;
122
+ HashCode() {
123
+ int h = rng.nextInt(); // Avoid zero to allow xorShift rehash
124
+ code = (h == 0) ? 1 : h;
125
+ }
126
+ }
127
+
128
+ /**
129
+ * The corresponding ThreadLocal class
130
+ */
131
+ static final class ThreadHashCode extends ThreadLocal<HashCode> {
132
+ public HashCode initialValue() { return new HashCode(); }
133
+ }
134
+
135
+ /**
136
+ * Static per-thread hash codes. Shared across all instances to
137
+ * reduce ThreadLocal pollution and because adjustments due to
138
+ * collisions in one table are likely to be appropriate for
139
+ * others.
140
+ */
141
+ static final ThreadHashCode threadHashCode = new ThreadHashCode();
142
+
143
+ /** Number of CPUS, to place bound on table size */
144
+ static final int NCPU = Runtime.getRuntime().availableProcessors();
145
+
146
+ /**
147
+ * Table of cells. When non-null, size is a power of 2.
148
+ */
149
+ transient volatile Cell[] cells;
150
+
151
+ /**
152
+ * Base value, used mainly when there is no contention, but also as
153
+ * a fallback during table initialization races. Updated via CAS.
154
+ */
155
+ transient volatile long base;
156
+
157
+ /**
158
+ * Spinlock (locked via CAS) used when resizing and/or creating Cells.
159
+ */
160
+ transient volatile int busy;
161
+
162
+ /**
163
+ * Package-private default constructor
164
+ */
165
+ Striped64() {
166
+ }
167
+
168
+ /**
169
+ * CASes the base field.
170
+ */
171
+ final boolean casBase(long cmp, long val) {
172
+ return UNSAFE.compareAndSwapLong(this, baseOffset, cmp, val);
173
+ }
174
+
175
+ /**
176
+ * CASes the busy field from 0 to 1 to acquire lock.
177
+ */
178
+ final boolean casBusy() {
179
+ return UNSAFE.compareAndSwapInt(this, busyOffset, 0, 1);
180
+ }
181
+
182
+ /**
183
+ * Computes the function of current and new value. Subclasses
184
+ * should open-code this update function for most uses, but the
185
+ * virtualized form is needed within retryUpdate.
186
+ *
187
+ * @param currentValue the current value (of either base or a cell)
188
+ * @param newValue the argument from a user update call
189
+ * @return result of the update function
190
+ */
191
+ abstract long fn(long currentValue, long newValue);
192
+
193
+ /**
194
+ * Handles cases of updates involving initialization, resizing,
195
+ * creating new Cells, and/or contention. See above for
196
+ * explanation. This method suffers the usual non-modularity
197
+ * problems of optimistic retry code, relying on rechecked sets of
198
+ * reads.
199
+ *
200
+ * @param x the value
201
+ * @param hc the hash code holder
202
+ * @param wasUncontended false if CAS failed before call
203
+ */
204
+ final void retryUpdate(long x, HashCode hc, boolean wasUncontended) {
205
+ int h = hc.code;
206
+ boolean collide = false; // True if last slot nonempty
207
+ for (;;) {
208
+ Cell[] as; Cell a; int n; long v;
209
+ if ((as = cells) != null && (n = as.length) > 0) {
210
+ if ((a = as[(n - 1) & h]) == null) {
211
+ if (busy == 0) { // Try to attach new Cell
212
+ Cell r = new Cell(x); // Optimistically create
213
+ if (busy == 0 && casBusy()) {
214
+ boolean created = false;
215
+ try { // Recheck under lock
216
+ Cell[] rs; int m, j;
217
+ if ((rs = cells) != null &&
218
+ (m = rs.length) > 0 &&
219
+ rs[j = (m - 1) & h] == null) {
220
+ rs[j] = r;
221
+ created = true;
222
+ }
223
+ } finally {
224
+ busy = 0;
225
+ }
226
+ if (created)
227
+ break;
228
+ continue; // Slot is now non-empty
229
+ }
230
+ }
231
+ collide = false;
232
+ }
233
+ else if (!wasUncontended) // CAS already known to fail
234
+ wasUncontended = true; // Continue after rehash
235
+ else if (a.cas(v = a.value, fn(v, x)))
236
+ break;
237
+ else if (n >= NCPU || cells != as)
238
+ collide = false; // At max size or stale
239
+ else if (!collide)
240
+ collide = true;
241
+ else if (busy == 0 && casBusy()) {
242
+ try {
243
+ if (cells == as) { // Expand table unless stale
244
+ Cell[] rs = new Cell[n << 1];
245
+ for (int i = 0; i < n; ++i)
246
+ rs[i] = as[i];
247
+ cells = rs;
248
+ }
249
+ } finally {
250
+ busy = 0;
251
+ }
252
+ collide = false;
253
+ continue; // Retry with expanded table
254
+ }
255
+ h ^= h << 13; // Rehash
256
+ h ^= h >>> 17;
257
+ h ^= h << 5;
258
+ }
259
+ else if (busy == 0 && cells == as && casBusy()) {
260
+ boolean init = false;
261
+ try { // Initialize table
262
+ if (cells == as) {
263
+ Cell[] rs = new Cell[2];
264
+ rs[h & 1] = new Cell(x);
265
+ cells = rs;
266
+ init = true;
267
+ }
268
+ } finally {
269
+ busy = 0;
270
+ }
271
+ if (init)
272
+ break;
273
+ }
274
+ else if (casBase(v = base, fn(v, x)))
275
+ break; // Fall back on using base
276
+ }
277
+ hc.code = h; // Record index for next time
278
+ }
279
+
280
+
281
+ /**
282
+ * Sets base and all cells to the given value.
283
+ */
284
+ final void internalReset(long initialValue) {
285
+ Cell[] as = cells;
286
+ base = initialValue;
287
+ if (as != null) {
288
+ int n = as.length;
289
+ for (int i = 0; i < n; ++i) {
290
+ Cell a = as[i];
291
+ if (a != null)
292
+ a.value = initialValue;
293
+ }
294
+ }
295
+ }
296
+
297
+ // Unsafe mechanics
298
+ private static final sun.misc.Unsafe UNSAFE;
299
+ private static final long baseOffset;
300
+ private static final long busyOffset;
301
+ static {
302
+ try {
303
+ UNSAFE = getUnsafe();
304
+ Class<?> sk = Striped64.class;
305
+ baseOffset = UNSAFE.objectFieldOffset
306
+ (sk.getDeclaredField("base"));
307
+ busyOffset = UNSAFE.objectFieldOffset
308
+ (sk.getDeclaredField("busy"));
309
+ } catch (Exception e) {
310
+ throw new Error(e);
311
+ }
312
+ }
313
+
314
+ /**
315
+ * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
316
+ * Replace with a simple call to Unsafe.getUnsafe when integrating
317
+ * into a jdk.
318
+ *
319
+ * @return a sun.misc.Unsafe
320
+ */
321
+ private static sun.misc.Unsafe getUnsafe() {
322
+ try {
323
+ return sun.misc.Unsafe.getUnsafe();
324
+ } catch (SecurityException se) {
325
+ try {
326
+ return java.security.AccessController.doPrivileged
327
+ (new java.security
328
+ .PrivilegedExceptionAction<sun.misc.Unsafe>() {
329
+ public sun.misc.Unsafe run() throws Exception {
330
+ java.lang.reflect.Field f = sun.misc
331
+ .Unsafe.class.getDeclaredField("theUnsafe");
332
+ f.setAccessible(true);
333
+ return (sun.misc.Unsafe) f.get(null);
334
+ }});
335
+ } catch (java.security.PrivilegedActionException e) {
336
+ throw new RuntimeException("Could not initialize intrinsics",
337
+ e.getCause());
338
+ }
339
+ }
340
+ }
341
+
342
+ }