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