32 * Expert Group and released to the public domain, as explained at |
32 * Expert Group and released to the public domain, as explained at |
33 * http://creativecommons.org/publicdomain/zero/1.0/ |
33 * http://creativecommons.org/publicdomain/zero/1.0/ |
34 */ |
34 */ |
35 |
35 |
36 package java.util.concurrent.atomic; |
36 package java.util.concurrent.atomic; |
37 |
|
38 import java.util.Arrays; |
|
39 import java.util.function.UnaryOperator; |
37 import java.util.function.UnaryOperator; |
40 import java.util.function.BinaryOperator; |
38 import java.util.function.BinaryOperator; |
|
39 import java.util.Arrays; |
41 import java.lang.reflect.Array; |
40 import java.lang.reflect.Array; |
42 import sun.misc.Unsafe; |
41 import sun.misc.Unsafe; |
43 |
42 |
44 /** |
43 /** |
45 * An array of object references in which elements may be updated |
44 * An array of object references in which elements may be updated |
58 private static final int shift; |
57 private static final int shift; |
59 private static final long arrayFieldOffset; |
58 private static final long arrayFieldOffset; |
60 private final Object[] array; // must have exact type Object[] |
59 private final Object[] array; // must have exact type Object[] |
61 |
60 |
62 static { |
61 static { |
63 int scale; |
|
64 try { |
62 try { |
65 unsafe = Unsafe.getUnsafe(); |
63 unsafe = Unsafe.getUnsafe(); |
66 arrayFieldOffset = unsafe.objectFieldOffset |
64 arrayFieldOffset = unsafe.objectFieldOffset |
67 (AtomicReferenceArray.class.getDeclaredField("array")); |
65 (AtomicReferenceArray.class.getDeclaredField("array")); |
68 base = unsafe.arrayBaseOffset(Object[].class); |
66 base = unsafe.arrayBaseOffset(Object[].class); |
69 scale = unsafe.arrayIndexScale(Object[].class); |
67 int scale = unsafe.arrayIndexScale(Object[].class); |
|
68 if ((scale & (scale - 1)) != 0) |
|
69 throw new Error("data type scale not a power of two"); |
|
70 shift = 31 - Integer.numberOfLeadingZeros(scale); |
70 } catch (Exception e) { |
71 } catch (Exception e) { |
71 throw new Error(e); |
72 throw new Error(e); |
72 } |
73 } |
73 if ((scale & (scale - 1)) != 0) |
|
74 throw new Error("data type scale not a power of two"); |
|
75 shift = 31 - Integer.numberOfLeadingZeros(scale); |
|
76 } |
74 } |
77 |
75 |
78 private long checkedByteOffset(int i) { |
76 private long checkedByteOffset(int i) { |
79 if (i < 0 || i >= array.length) |
77 if (i < 0 || i >= array.length) |
80 throw new IndexOutOfBoundsException("index " + i); |
78 throw new IndexOutOfBoundsException("index " + i); |
171 * updated value if the current value {@code ==} the expected value. |
169 * updated value if the current value {@code ==} the expected value. |
172 * |
170 * |
173 * @param i the index |
171 * @param i the index |
174 * @param expect the expected value |
172 * @param expect the expected value |
175 * @param update the new value |
173 * @param update the new value |
176 * @return true if successful. False return indicates that |
174 * @return {@code true} if successful. False return indicates that |
177 * the actual value was not equal to the expected value. |
175 * the actual value was not equal to the expected value. |
178 */ |
176 */ |
179 public final boolean compareAndSet(int i, E expect, E update) { |
177 public final boolean compareAndSet(int i, E expect, E update) { |
180 return compareAndSetRaw(checkedByteOffset(i), expect, update); |
178 return compareAndSetRaw(checkedByteOffset(i), expect, update); |
181 } |
179 } |
186 |
184 |
187 /** |
185 /** |
188 * Atomically sets the element at position {@code i} to the given |
186 * Atomically sets the element at position {@code i} to the given |
189 * updated value if the current value {@code ==} the expected value. |
187 * updated value if the current value {@code ==} the expected value. |
190 * |
188 * |
191 * <p>May <a href="package-summary.html#Spurious">fail spuriously</a> |
189 * <p><a href="package-summary.html#weakCompareAndSet">May fail |
192 * and does not provide ordering guarantees, so is only rarely an |
190 * spuriously and does not provide ordering guarantees</a>, so is |
193 * appropriate alternative to {@code compareAndSet}. |
191 * only rarely an appropriate alternative to {@code compareAndSet}. |
194 * |
192 * |
195 * @param i the index |
193 * @param i the index |
196 * @param expect the expected value |
194 * @param expect the expected value |
197 * @param update the new value |
195 * @param update the new value |
198 * @return true if successful |
196 * @return {@code true} if successful |
199 */ |
197 */ |
200 public final boolean weakCompareAndSet(int i, E expect, E update) { |
198 public final boolean weakCompareAndSet(int i, E expect, E update) { |
201 return compareAndSet(i, expect, update); |
199 return compareAndSet(i, expect, update); |
202 } |
200 } |
203 |
201 |
204 /** |
202 /** |
205 * Atomically updates the element at index {@code i} with the results |
203 * Atomically updates the element at index {@code i} with the results |
206 * of applying the given function, returning the previous value. The |
204 * of applying the given function, returning the previous value. The |
207 * function should be side-effect-free, since it may be re-applied |
205 * function should be side-effect-free, since it may be re-applied |
208 * when attempted updates fail due to contention among threads. |
206 * when attempted updates fail due to contention among threads. |
209 * |
207 * |