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