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.lang.invoke.MethodHandles; |
10 |
import java.lang.invoke.VarHandle; |
11 |
import java.util.function.LongBinaryOperator; |
12 |
import java.util.function.LongUnaryOperator; |
13 |
|
14 |
/** |
15 |
* A {@code long} array in which elements may be updated atomically. |
16 |
* See the {@link VarHandle} specification for descriptions of the |
17 |
* properties of atomic accesses. |
18 |
* @since 1.5 |
19 |
* @author Doug Lea |
20 |
*/ |
21 |
public class AtomicLongArray implements java.io.Serializable { |
22 |
private static final long serialVersionUID = -2308431214976778248L; |
23 |
private static final VarHandle AA |
24 |
= MethodHandles.arrayElementVarHandle(long[].class); |
25 |
private final long[] array; |
26 |
|
27 |
/** |
28 |
* Creates a new AtomicLongArray of the given length, with all |
29 |
* elements initially zero. |
30 |
* |
31 |
* @param length the length of the array |
32 |
*/ |
33 |
public AtomicLongArray(int length) { |
34 |
array = new long[length]; |
35 |
} |
36 |
|
37 |
/** |
38 |
* Creates a new AtomicLongArray with the same length as, and |
39 |
* all elements copied from, the given array. |
40 |
* |
41 |
* @param array the array to copy elements from |
42 |
* @throws NullPointerException if array is null |
43 |
*/ |
44 |
public AtomicLongArray(long[] array) { |
45 |
// Visibility guaranteed by final field guarantees |
46 |
this.array = array.clone(); |
47 |
} |
48 |
|
49 |
/** |
50 |
* Returns the length of the array. |
51 |
* |
52 |
* @return the length of the array |
53 |
*/ |
54 |
public final int length() { |
55 |
return array.length; |
56 |
} |
57 |
|
58 |
/** |
59 |
* Returns the current value of the element at index {@code i}, |
60 |
* with memory effects as specified by {@link VarHandle#getVolatile}. |
61 |
* |
62 |
* @param i the index |
63 |
* @return the current value |
64 |
*/ |
65 |
public final long get(int i) { |
66 |
return (long)AA.getVolatile(array, i); |
67 |
} |
68 |
|
69 |
/** |
70 |
* Sets the element at index {@code i} to {@code newValue}, |
71 |
* with memory effects as specified by {@link VarHandle#setVolatile}. |
72 |
* |
73 |
* @param i the index |
74 |
* @param newValue the new value |
75 |
*/ |
76 |
public final void set(int i, long newValue) { |
77 |
AA.setVolatile(array, i, newValue); |
78 |
} |
79 |
|
80 |
/** |
81 |
* Sets the element at index {@code i} to {@code newValue}, |
82 |
* with memory effects as specified by {@link VarHandle#setRelease}. |
83 |
* |
84 |
* @param i the index |
85 |
* @param newValue the new value |
86 |
* @since 1.6 |
87 |
*/ |
88 |
public final void lazySet(int i, long newValue) { |
89 |
AA.setRelease(array, i, newValue); |
90 |
} |
91 |
|
92 |
/** |
93 |
* Atomically sets the element at index {@code i} to {@code |
94 |
* newValue} and returns the old value, |
95 |
* with memory effects as specified by {@link VarHandle#getAndSet}. |
96 |
* |
97 |
* @param i the index |
98 |
* @param newValue the new value |
99 |
* @return the previous value |
100 |
*/ |
101 |
public final long getAndSet(int i, long newValue) { |
102 |
return (long)AA.getAndSet(array, i, newValue); |
103 |
} |
104 |
|
105 |
/** |
106 |
* Atomically sets the element at index {@code i} to {@code newValue} |
107 |
* if the element's current value {@code == expectedValue}, |
108 |
* with memory effects as specified by {@link VarHandle#compareAndSet}. |
109 |
* |
110 |
* @param i the index |
111 |
* @param expectedValue the expected value |
112 |
* @param newValue the new value |
113 |
* @return {@code true} if successful. False return indicates that |
114 |
* the actual value was not equal to the expected value. |
115 |
*/ |
116 |
public final boolean compareAndSet(int i, long expectedValue, long newValue) { |
117 |
return AA.compareAndSet(array, i, expectedValue, newValue); |
118 |
} |
119 |
|
120 |
/** |
121 |
* Possibly atomically sets the element at index {@code i} to |
122 |
* {@code newValue} if the element's current value {@code == expectedValue}, |
123 |
* with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. |
124 |
* |
125 |
* @deprecated This method has plain memory effects but the method |
126 |
* name implies volatile memory effects (see methods such as |
127 |
* {@link #compareAndExchange} and {@link #compareAndSet}). To avoid |
128 |
* confusion over plain or volatile memory effects it is recommended that |
129 |
* the method {@link #weakCompareAndSetPlain} be used instead. |
130 |
* |
131 |
* @param i the index |
132 |
* @param expectedValue the expected value |
133 |
* @param newValue the new value |
134 |
* @return {@code true} if successful |
135 |
* @see #weakCompareAndSetPlain |
136 |
*/ |
137 |
@Deprecated(since="9") |
138 |
public final boolean weakCompareAndSet(int i, long expectedValue, long newValue) { |
139 |
return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue); |
140 |
} |
141 |
|
142 |
/** |
143 |
* Possibly atomically sets the element at index {@code i} to |
144 |
* {@code newValue} if the element's current value {@code == expectedValue}, |
145 |
* with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. |
146 |
* |
147 |
* @param i the index |
148 |
* @param expectedValue the expected value |
149 |
* @param newValue the new value |
150 |
* @return {@code true} if successful |
151 |
* @since 9 |
152 |
*/ |
153 |
public final boolean weakCompareAndSetPlain(int i, long expectedValue, long newValue) { |
154 |
return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue); |
155 |
} |
156 |
|
157 |
/** |
158 |
* Atomically increments the value of the element at index {@code i}, |
159 |
* with memory effects as specified by {@link VarHandle#getAndAdd}. |
160 |
* |
161 |
* <p>Equivalent to {@code getAndAdd(i, 1)}. |
162 |
* |
163 |
* @param i the index |
164 |
* @return the previous value |
165 |
*/ |
166 |
public final long getAndIncrement(int i) { |
167 |
return (long)AA.getAndAdd(array, i, 1L); |
168 |
} |
169 |
|
170 |
/** |
171 |
* Atomically decrements the value of the element at index {@code i}, |
172 |
* with memory effects as specified by {@link VarHandle#getAndAdd}. |
173 |
* |
174 |
* <p>Equivalent to {@code getAndAdd(i, -1)}. |
175 |
* |
176 |
* @param i the index |
177 |
* @return the previous value |
178 |
*/ |
179 |
public final long getAndDecrement(int i) { |
180 |
return (long)AA.getAndAdd(array, i, -1L); |
181 |
} |
182 |
|
183 |
/** |
184 |
* Atomically adds the given value to the element at index {@code i}, |
185 |
* with memory effects as specified by {@link VarHandle#getAndAdd}. |
186 |
* |
187 |
* @param i the index |
188 |
* @param delta the value to add |
189 |
* @return the previous value |
190 |
*/ |
191 |
public final long getAndAdd(int i, long delta) { |
192 |
return (long)AA.getAndAdd(array, i, delta); |
193 |
} |
194 |
|
195 |
/** |
196 |
* Atomically increments the value of the element at index {@code i}, |
197 |
* with memory effects as specified by {@link VarHandle#getAndAdd}. |
198 |
* |
199 |
* <p>Equivalent to {@code addAndGet(i, 1)}. |
200 |
* |
201 |
* @param i the index |
202 |
* @return the updated value |
203 |
*/ |
204 |
public final long incrementAndGet(int i) { |
205 |
return (long)AA.getAndAdd(array, i, 1L) + 1L; |
206 |
} |
207 |
|
208 |
/** |
209 |
* Atomically decrements the value of the element at index {@code i}, |
210 |
* with memory effects as specified by {@link VarHandle#getAndAdd}. |
211 |
* |
212 |
* <p>Equivalent to {@code addAndGet(i, -1)}. |
213 |
* |
214 |
* @param i the index |
215 |
* @return the updated value |
216 |
*/ |
217 |
public final long decrementAndGet(int i) { |
218 |
return (long)AA.getAndAdd(array, i, -1L) - 1L; |
219 |
} |
220 |
|
221 |
/** |
222 |
* Atomically adds the given value to the element at index {@code i}, |
223 |
* with memory effects as specified by {@link VarHandle#getAndAdd}. |
224 |
* |
225 |
* @param i the index |
226 |
* @param delta the value to add |
227 |
* @return the updated value |
228 |
*/ |
229 |
public long addAndGet(int i, long delta) { |
230 |
return (long)AA.getAndAdd(array, i, delta) + delta; |
231 |
} |
232 |
|
233 |
/** |
234 |
* Atomically updates (with memory effects as specified by {@link |
235 |
* VarHandle#compareAndSet}) the element at index {@code i} with |
236 |
* the results of applying the given function, returning the |
237 |
* previous value. The function should be side-effect-free, since |
238 |
* it may be re-applied when attempted updates fail due to |
239 |
* contention among threads. |
240 |
* |
241 |
* @param i the index |
242 |
* @param updateFunction a side-effect-free function |
243 |
* @return the previous value |
244 |
* @since 1.8 |
245 |
*/ |
246 |
public final long getAndUpdate(int i, LongUnaryOperator updateFunction) { |
247 |
long prev = get(i), next = 0L; |
248 |
for (boolean haveNext = false;;) { |
249 |
if (!haveNext) |
250 |
next = updateFunction.applyAsLong(prev); |
251 |
if (weakCompareAndSetVolatile(i, prev, next)) |
252 |
return prev; |
253 |
haveNext = (prev == (prev = get(i))); |
254 |
} |
255 |
} |
256 |
|
257 |
/** |
258 |
* Atomically updates (with memory effects as specified by {@link |
259 |
* VarHandle#compareAndSet}) the element at index {@code i} with |
260 |
* the results of applying the given function, returning the |
261 |
* updated value. The function should be side-effect-free, since it |
262 |
* may be re-applied when attempted updates fail due to contention |
263 |
* among threads. |
264 |
* |
265 |
* @param i the index |
266 |
* @param updateFunction a side-effect-free function |
267 |
* @return the updated value |
268 |
* @since 1.8 |
269 |
*/ |
270 |
public final long updateAndGet(int i, LongUnaryOperator updateFunction) { |
271 |
long prev = get(i), next = 0L; |
272 |
for (boolean haveNext = false;;) { |
273 |
if (!haveNext) |
274 |
next = updateFunction.applyAsLong(prev); |
275 |
if (weakCompareAndSetVolatile(i, prev, next)) |
276 |
return next; |
277 |
haveNext = (prev == (prev = get(i))); |
278 |
} |
279 |
} |
280 |
|
281 |
/** |
282 |
* Atomically updates (with memory effects as specified by {@link |
283 |
* VarHandle#compareAndSet}) the element at index {@code i} with |
284 |
* the results of applying the given function to the current and |
285 |
* given values, returning the previous value. The function should |
286 |
* be side-effect-free, since it may be re-applied when attempted |
287 |
* updates fail due to contention among threads. The function is |
288 |
* applied with the current value of the element at index {@code i} |
289 |
* as its first argument, and the given update as the second |
290 |
* argument. |
291 |
* |
292 |
* @param i the index |
293 |
* @param x the update value |
294 |
* @param accumulatorFunction a side-effect-free function of two arguments |
295 |
* @return the previous value |
296 |
* @since 1.8 |
297 |
*/ |
298 |
public final long getAndAccumulate(int i, long x, |
299 |
LongBinaryOperator accumulatorFunction) { |
300 |
long prev = get(i), next = 0L; |
301 |
for (boolean haveNext = false;;) { |
302 |
if (!haveNext) |
303 |
next = accumulatorFunction.applyAsLong(prev, x); |
304 |
if (weakCompareAndSetVolatile(i, prev, next)) |
305 |
return prev; |
306 |
haveNext = (prev == (prev = get(i))); |
307 |
} |
308 |
} |
309 |
|
310 |
/** |
311 |
* Atomically updates (with memory effects as specified by {@link |
312 |
* VarHandle#compareAndSet}) the element at index {@code i} with |
313 |
* the results of applying the given function to the current and |
314 |
* given values, returning the updated value. The function should |
315 |
* be side-effect-free, since it may be re-applied when attempted |
316 |
* updates fail due to contention among threads. The function is |
317 |
* applied with the current value of the element at index {@code i} |
318 |
* as its first argument, and the given update as the second |
319 |
* argument. |
320 |
* |
321 |
* @param i the index |
322 |
* @param x the update value |
323 |
* @param accumulatorFunction a side-effect-free function of two arguments |
324 |
* @return the updated value |
325 |
* @since 1.8 |
326 |
*/ |
327 |
public final long accumulateAndGet(int i, long x, |
328 |
LongBinaryOperator accumulatorFunction) { |
329 |
long prev = get(i), next = 0L; |
330 |
for (boolean haveNext = false;;) { |
331 |
if (!haveNext) |
332 |
next = accumulatorFunction.applyAsLong(prev, x); |
333 |
if (weakCompareAndSetVolatile(i, prev, next)) |
334 |
return next; |
335 |
haveNext = (prev == (prev = get(i))); |
336 |
} |
337 |
} |
338 |
|
339 |
/** |
340 |
* Returns the String representation of the current values of array. |
341 |
* @return the String representation of the current values of array |
342 |
*/ |
343 |
public String toString() { |
344 |
int iMax = array.length - 1; |
345 |
if (iMax == -1) |
346 |
return "[]"; |
347 |
|
348 |
StringBuilder b = new StringBuilder(); |
349 |
b.append('['); |
350 |
for (int i = 0; ; i++) { |
351 |
b.append(get(i)); |
352 |
if (i == iMax) |
353 |
return b.append(']').toString(); |
354 |
b.append(',').append(' '); |
355 |
} |
356 |
} |
357 |
|
358 |
// jdk9 |
359 |
|
360 |
/** |
361 |
* Returns the current value of the element at index {@code i}, |
362 |
* with memory semantics of reading as if the variable was declared |
363 |
* non-{@code volatile}. |
364 |
* |
365 |
* @param i the index |
366 |
* @return the value |
367 |
* @since 9 |
368 |
*/ |
369 |
public final long getPlain(int i) { |
370 |
return (long)AA.get(array, i); |
371 |
} |
372 |
|
373 |
/** |
374 |
* Sets the element at index {@code i} to {@code newValue}, |
375 |
* with memory semantics of setting as if the variable was |
376 |
* declared non-{@code volatile} and non-{@code final}. |
377 |
* |
378 |
* @param i the index |
379 |
* @param newValue the new value |
380 |
* @since 9 |
381 |
*/ |
382 |
public final void setPlain(int i, long newValue) { |
383 |
AA.set(array, i, newValue); |
384 |
} |
385 |
|
386 |
/** |
387 |
* Returns the current value of the element at index {@code i}, |
388 |
* with memory effects as specified by {@link VarHandle#getOpaque}. |
389 |
* |
390 |
* @param i the index |
391 |
* @return the value |
392 |
* @since 9 |
393 |
*/ |
394 |
public final long getOpaque(int i) { |
395 |
return (long)AA.getOpaque(array, i); |
396 |
} |
397 |
|
398 |
/** |
399 |
* Sets the element at index {@code i} to {@code newValue}, |
400 |
* with memory effects as specified by {@link VarHandle#setOpaque}. |
401 |
* |
402 |
* @param i the index |
403 |
* @param newValue the new value |
404 |
* @since 9 |
405 |
*/ |
406 |
public final void setOpaque(int i, long newValue) { |
407 |
AA.setOpaque(array, i, newValue); |
408 |
} |
409 |
|
410 |
/** |
411 |
* Returns the current value of the element at index {@code i}, |
412 |
* with memory effects as specified by {@link VarHandle#getAcquire}. |
413 |
* |
414 |
* @param i the index |
415 |
* @return the value |
416 |
* @since 9 |
417 |
*/ |
418 |
public final long getAcquire(int i) { |
419 |
return (long)AA.getAcquire(array, i); |
420 |
} |
421 |
|
422 |
/** |
423 |
* Sets the element at index {@code i} to {@code newValue}, |
424 |
* with memory effects as specified by {@link VarHandle#setRelease}. |
425 |
* |
426 |
* @param i the index |
427 |
* @param newValue the new value |
428 |
* @since 9 |
429 |
*/ |
430 |
public final void setRelease(int i, long newValue) { |
431 |
AA.setRelease(array, i, newValue); |
432 |
} |
433 |
|
434 |
/** |
435 |
* Atomically sets the element at index {@code i} to {@code newValue} |
436 |
* if the element's current value, referred to as the <em>witness |
437 |
* value</em>, {@code == expectedValue}, |
438 |
* with memory effects as specified by |
439 |
* {@link VarHandle#compareAndExchange}. |
440 |
* |
441 |
* @param i the index |
442 |
* @param expectedValue the expected value |
443 |
* @param newValue the new value |
444 |
* @return the witness value, which will be the same as the |
445 |
* expected value if successful |
446 |
* @since 9 |
447 |
*/ |
448 |
public final long compareAndExchange(int i, long expectedValue, long newValue) { |
449 |
return (long)AA.compareAndExchange(array, i, expectedValue, newValue); |
450 |
} |
451 |
|
452 |
/** |
453 |
* Atomically sets the element at index {@code i} to {@code newValue} |
454 |
* if the element's current value, referred to as the <em>witness |
455 |
* value</em>, {@code == expectedValue}, |
456 |
* with memory effects as specified by |
457 |
* {@link VarHandle#compareAndExchangeAcquire}. |
458 |
* |
459 |
* @param i the index |
460 |
* @param expectedValue the expected value |
461 |
* @param newValue the new value |
462 |
* @return the witness value, which will be the same as the |
463 |
* expected value if successful |
464 |
* @since 9 |
465 |
*/ |
466 |
public final long compareAndExchangeAcquire(int i, long expectedValue, long newValue) { |
467 |
return (long)AA.compareAndExchangeAcquire(array, i, expectedValue, newValue); |
468 |
} |
469 |
|
470 |
/** |
471 |
* Atomically sets the element at index {@code i} to {@code newValue} |
472 |
* if the element's current value, referred to as the <em>witness |
473 |
* value</em>, {@code == expectedValue}, |
474 |
* with memory effects as specified by |
475 |
* {@link VarHandle#compareAndExchangeRelease}. |
476 |
* |
477 |
* @param i the index |
478 |
* @param expectedValue the expected value |
479 |
* @param newValue the new value |
480 |
* @return the witness value, which will be the same as the |
481 |
* expected value if successful |
482 |
* @since 9 |
483 |
*/ |
484 |
public final long compareAndExchangeRelease(int i, long expectedValue, long newValue) { |
485 |
return (long)AA.compareAndExchangeRelease(array, i, expectedValue, newValue); |
486 |
} |
487 |
|
488 |
/** |
489 |
* Possibly atomically sets the element at index {@code i} to |
490 |
* {@code newValue} if the element's current value {@code == expectedValue}, |
491 |
* with memory effects as specified by |
492 |
* {@link VarHandle#weakCompareAndSet}. |
493 |
* |
494 |
* @param i the index |
495 |
* @param expectedValue the expected value |
496 |
* @param newValue the new value |
497 |
* @return {@code true} if successful |
498 |
* @since 9 |
499 |
*/ |
500 |
public final boolean weakCompareAndSetVolatile(int i, long expectedValue, long newValue) { |
501 |
return AA.weakCompareAndSet(array, i, expectedValue, newValue); |
502 |
} |
503 |
|
504 |
/** |
505 |
* Possibly atomically sets the element at index {@code i} to |
506 |
* {@code newValue} if the element's current value {@code == expectedValue}, |
507 |
* with memory effects as specified by |
508 |
* {@link VarHandle#weakCompareAndSetAcquire}. |
509 |
* |
510 |
* @param i the index |
511 |
* @param expectedValue the expected value |
512 |
* @param newValue the new value |
513 |
* @return {@code true} if successful |
514 |
* @since 9 |
515 |
*/ |
516 |
public final boolean weakCompareAndSetAcquire(int i, long expectedValue, long newValue) { |
517 |
return AA.weakCompareAndSetAcquire(array, i, expectedValue, newValue); |
518 |
} |
519 |
|
520 |
/** |
521 |
* Possibly atomically sets the element at index {@code i} to |
522 |
* {@code newValue} if the element's current value {@code == expectedValue}, |
523 |
* with memory effects as specified by |
524 |
* {@link VarHandle#weakCompareAndSetRelease}. |
525 |
* |
526 |
* @param i the index |
527 |
* @param expectedValue the expected value |
528 |
* @param newValue the new value |
529 |
* @return {@code true} if successful |
530 |
* @since 9 |
531 |
*/ |
532 |
public final boolean weakCompareAndSetRelease(int i, long expectedValue, long newValue) { |
533 |
return AA.weakCompareAndSetRelease(array, i, expectedValue, newValue); |
534 |
} |
535 |
|
536 |
} |