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