ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/atomic/AtomicIntegerArray.java
Revision: 1.60
Committed: Fri Jun 9 22:39:59 2017 UTC (7 years ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.59: +22 -16 lines
Log Message:
8181104: Fix specs for updateAndGet and related methods

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.lang.invoke.MethodHandles;
10 import java.lang.invoke.VarHandle;
11 import java.util.function.IntBinaryOperator;
12 import java.util.function.IntUnaryOperator;
13
14 /**
15 * An {@code int} 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 AtomicIntegerArray implements java.io.Serializable {
22 private static final long serialVersionUID = 2862133569453604235L;
23 private static final VarHandle AA
24 = MethodHandles.arrayElementVarHandle(int[].class);
25 private final int[] array;
26
27 /**
28 * Creates a new AtomicIntegerArray of the given length, with all
29 * elements initially zero.
30 *
31 * @param length the length of the array
32 */
33 public AtomicIntegerArray(int length) {
34 array = new int[length];
35 }
36
37 /**
38 * Creates a new AtomicIntegerArray 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 AtomicIntegerArray(int[] 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 int get(int i) {
66 return (int)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, int 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, int 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 int getAndSet(int i, int newValue) {
102 return (int)AA.getAndSet(array, i, newValue);
103 }
104
105 /**
106 * Atomically sets the element at index {@code i} to {@code
107 * newValue} 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, int expectedValue, int 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, int expectedValue, int 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, int expectedValue, int 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 int getAndIncrement(int i) {
167 return (int)AA.getAndAdd(array, i, 1);
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 int getAndDecrement(int i) {
180 return (int)AA.getAndAdd(array, i, -1);
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 int getAndAdd(int i, int delta) {
192 return (int)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 int incrementAndGet(int i) {
205 return (int)AA.getAndAdd(array, i, 1) + 1;
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 int decrementAndGet(int i) {
218 return (int)AA.getAndAdd(array, i, -1) - 1;
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 final int addAndGet(int i, int delta) {
230 return (int)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 int getAndUpdate(int i, IntUnaryOperator updateFunction) {
247 int prev = get(i), next = 0;
248 for (boolean haveNext = false;;) {
249 if (!haveNext)
250 next = updateFunction.applyAsInt(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 int updateAndGet(int i, IntUnaryOperator updateFunction) {
271 int prev = get(i), next = 0;
272 for (boolean haveNext = false;;) {
273 if (!haveNext)
274 next = updateFunction.applyAsInt(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 int getAndAccumulate(int i, int x,
299 IntBinaryOperator accumulatorFunction) {
300 int prev = get(i), next = 0;
301 for (boolean haveNext = false;;) {
302 if (!haveNext)
303 next = accumulatorFunction.applyAsInt(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 int accumulateAndGet(int i, int x,
328 IntBinaryOperator accumulatorFunction) {
329 int prev = get(i), next = 0;
330 for (boolean haveNext = false;;) {
331 if (!haveNext)
332 next = accumulatorFunction.applyAsInt(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 int getPlain(int i) {
370 return (int)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, int 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 int getOpaque(int i) {
395 return (int)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, int 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 int getAcquire(int i) {
419 return (int)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, int 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 int compareAndExchange(int i, int expectedValue, int newValue) {
449 return (int)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 int compareAndExchangeAcquire(int i, int expectedValue, int newValue) {
467 return (int)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 int compareAndExchangeRelease(int i, int expectedValue, int newValue) {
485 return (int)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, int expectedValue, int 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, int expectedValue, int 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, int expectedValue, int newValue) {
533 return AA.weakCompareAndSetRelease(array, i, expectedValue, newValue);
534 }
535
536
537 }