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 trueif 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 trueif 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 trueif 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 trueif 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 trueif 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 trueif 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