ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk8/java/util/concurrent/atomic/AtomicLongArray.java
Revision: 1.1
Committed: Sat Mar 26 06:22:51 2016 UTC (8 years, 2 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Log Message:
fork jdk8 maintenance branch for source and jtreg tests

File Contents

# Content
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 package java.util.concurrent.atomic;
8
9 import java.util.function.LongBinaryOperator;
10 import java.util.function.LongUnaryOperator;
11
12 /**
13 * A {@code long} array in which elements may be updated atomically.
14 * See the {@link java.util.concurrent.atomic} package specification
15 * for description of the properties of atomic variables.
16 * @since 1.5
17 * @author Doug Lea
18 */
19 public class AtomicLongArray implements java.io.Serializable {
20 private static final long serialVersionUID = -2308431214976778248L;
21
22 private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
23 private static final int ABASE;
24 private static final int ASHIFT;
25 private final long[] array;
26
27 static {
28 ABASE = U.arrayBaseOffset(long[].class);
29 int scale = U.arrayIndexScale(long[].class);
30 if ((scale & (scale - 1)) != 0)
31 throw new Error("array index scale not a power of two");
32 ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
33 }
34
35 private long checkedByteOffset(int i) {
36 if (i < 0 || i >= array.length)
37 throw new IndexOutOfBoundsException("index " + i);
38
39 return byteOffset(i);
40 }
41
42 private static long byteOffset(int i) {
43 return ((long) i << ASHIFT) + ABASE;
44 }
45
46 /**
47 * Creates a new AtomicLongArray of the given length, with all
48 * elements initially zero.
49 *
50 * @param length the length of the array
51 */
52 public AtomicLongArray(int length) {
53 array = new long[length];
54 }
55
56 /**
57 * Creates a new AtomicLongArray with the same length as, and
58 * all elements copied from, the given array.
59 *
60 * @param array the array to copy elements from
61 * @throws NullPointerException if array is null
62 */
63 public AtomicLongArray(long[] array) {
64 // Visibility guaranteed by final field guarantees
65 this.array = array.clone();
66 }
67
68 /**
69 * Returns the length of the array.
70 *
71 * @return the length of the array
72 */
73 public final int length() {
74 return array.length;
75 }
76
77 /**
78 * Gets the current value at position {@code i}.
79 *
80 * @param i the index
81 * @return the current value
82 */
83 public final long get(int i) {
84 return getRaw(checkedByteOffset(i));
85 }
86
87 private long getRaw(long offset) {
88 return U.getLongVolatile(array, offset);
89 }
90
91 /**
92 * Sets the element at position {@code i} to the given value.
93 *
94 * @param i the index
95 * @param newValue the new value
96 */
97 public final void set(int i, long newValue) {
98 U.putLongVolatile(array, checkedByteOffset(i), newValue);
99 }
100
101 /**
102 * Eventually sets the element at position {@code i} to the given value.
103 *
104 * @param i the index
105 * @param newValue the new value
106 * @since 1.6
107 */
108 public final void lazySet(int i, long newValue) {
109 U.putOrderedLong(array, checkedByteOffset(i), newValue);
110 }
111
112 /**
113 * Atomically sets the element at position {@code i} to the given value
114 * and returns the old value.
115 *
116 * @param i the index
117 * @param newValue the new value
118 * @return the previous value
119 */
120 public final long getAndSet(int i, long newValue) {
121 return U.getAndSetLong(array, checkedByteOffset(i), newValue);
122 }
123
124 /**
125 * Atomically sets the element at position {@code i} to the given
126 * updated value if the current value {@code ==} the expected value.
127 *
128 * @param i the index
129 * @param expect the expected value
130 * @param update the new value
131 * @return {@code true} if successful. False return indicates that
132 * the actual value was not equal to the expected value.
133 */
134 public final boolean compareAndSet(int i, long expect, long update) {
135 return compareAndSetRaw(checkedByteOffset(i), expect, update);
136 }
137
138 private boolean compareAndSetRaw(long offset, long expect, long update) {
139 return U.compareAndSwapLong(array, offset, expect, update);
140 }
141
142 /**
143 * Atomically sets the element at position {@code i} to the given
144 * updated value if the current value {@code ==} the expected value.
145 *
146 * <p><a href="package-summary.html#weakCompareAndSet">May fail
147 * spuriously and does not provide ordering guarantees</a>, so is
148 * only rarely an appropriate alternative to {@code compareAndSet}.
149 *
150 * @param i the index
151 * @param expect the expected value
152 * @param update the new value
153 * @return {@code true} if successful
154 */
155 public final boolean weakCompareAndSet(int i, long expect, long update) {
156 return compareAndSet(i, expect, update);
157 }
158
159 /**
160 * Atomically increments by one the element at index {@code i}.
161 *
162 * @param i the index
163 * @return the previous value
164 */
165 public final long getAndIncrement(int i) {
166 return getAndAdd(i, 1);
167 }
168
169 /**
170 * Atomically decrements by one the element at index {@code i}.
171 *
172 * @param i the index
173 * @return the previous value
174 */
175 public final long getAndDecrement(int i) {
176 return getAndAdd(i, -1);
177 }
178
179 /**
180 * Atomically adds the given value to the element at index {@code i}.
181 *
182 * @param i the index
183 * @param delta the value to add
184 * @return the previous value
185 */
186 public final long getAndAdd(int i, long delta) {
187 return U.getAndAddLong(array, checkedByteOffset(i), delta);
188 }
189
190 /**
191 * Atomically increments by one the element at index {@code i}.
192 *
193 * @param i the index
194 * @return the updated value
195 */
196 public final long incrementAndGet(int i) {
197 return getAndAdd(i, 1) + 1;
198 }
199
200 /**
201 * Atomically decrements by one the element at index {@code i}.
202 *
203 * @param i the index
204 * @return the updated value
205 */
206 public final long decrementAndGet(int i) {
207 return getAndAdd(i, -1) - 1;
208 }
209
210 /**
211 * Atomically adds the given value to the element at index {@code i}.
212 *
213 * @param i the index
214 * @param delta the value to add
215 * @return the updated value
216 */
217 public long addAndGet(int i, long delta) {
218 return getAndAdd(i, delta) + delta;
219 }
220
221 /**
222 * Atomically updates the element at index {@code i} with the results
223 * of applying the given function, returning the previous value. The
224 * function should be side-effect-free, since it may be re-applied
225 * when attempted updates fail due to contention among threads.
226 *
227 * @param i the index
228 * @param updateFunction a side-effect-free function
229 * @return the previous value
230 * @since 1.8
231 */
232 public final long getAndUpdate(int i, LongUnaryOperator updateFunction) {
233 long offset = checkedByteOffset(i);
234 long prev, next;
235 do {
236 prev = getRaw(offset);
237 next = updateFunction.applyAsLong(prev);
238 } while (!compareAndSetRaw(offset, prev, next));
239 return prev;
240 }
241
242 /**
243 * Atomically updates the element at index {@code i} with the results
244 * of applying the given function, returning the updated value. The
245 * function should be side-effect-free, since it may be re-applied
246 * when attempted updates fail due to contention among threads.
247 *
248 * @param i the index
249 * @param updateFunction a side-effect-free function
250 * @return the updated value
251 * @since 1.8
252 */
253 public final long updateAndGet(int i, LongUnaryOperator updateFunction) {
254 long offset = checkedByteOffset(i);
255 long prev, next;
256 do {
257 prev = getRaw(offset);
258 next = updateFunction.applyAsLong(prev);
259 } while (!compareAndSetRaw(offset, prev, next));
260 return next;
261 }
262
263 /**
264 * Atomically updates the element at index {@code i} with the
265 * results of applying the given function to the current and
266 * given values, returning the previous value. The function should
267 * be side-effect-free, since it may be re-applied when attempted
268 * updates fail due to contention among threads. The function is
269 * applied with the current value at index {@code i} as its first
270 * argument, and the given update as the second argument.
271 *
272 * @param i the index
273 * @param x the update value
274 * @param accumulatorFunction a side-effect-free function of two arguments
275 * @return the previous value
276 * @since 1.8
277 */
278 public final long getAndAccumulate(int i, long x,
279 LongBinaryOperator accumulatorFunction) {
280 long offset = checkedByteOffset(i);
281 long prev, next;
282 do {
283 prev = getRaw(offset);
284 next = accumulatorFunction.applyAsLong(prev, x);
285 } while (!compareAndSetRaw(offset, prev, next));
286 return prev;
287 }
288
289 /**
290 * Atomically updates the element at index {@code i} with the
291 * results of applying the given function to the current and
292 * given values, returning the updated value. The function should
293 * be side-effect-free, since it may be re-applied when attempted
294 * updates fail due to contention among threads. The function is
295 * applied with the current value at index {@code i} as its first
296 * argument, and the given update as the second argument.
297 *
298 * @param i the index
299 * @param x the update value
300 * @param accumulatorFunction a side-effect-free function of two arguments
301 * @return the updated value
302 * @since 1.8
303 */
304 public final long accumulateAndGet(int i, long x,
305 LongBinaryOperator accumulatorFunction) {
306 long offset = checkedByteOffset(i);
307 long prev, next;
308 do {
309 prev = getRaw(offset);
310 next = accumulatorFunction.applyAsLong(prev, x);
311 } while (!compareAndSetRaw(offset, prev, next));
312 return next;
313 }
314
315 /**
316 * Returns the String representation of the current values of array.
317 * @return the String representation of the current values of array
318 */
319 public String toString() {
320 int iMax = array.length - 1;
321 if (iMax == -1)
322 return "[]";
323
324 StringBuilder b = new StringBuilder();
325 b.append('[');
326 for (int i = 0; ; i++) {
327 b.append(getRaw(byteOffset(i)));
328 if (i == iMax)
329 return b.append(']').toString();
330 b.append(',').append(' ');
331 }
332 }
333
334 }