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
36package java.util.concurrent.atomic;
37
38import java.lang.invoke.MethodHandles;
39import java.lang.invoke.VarHandle;
40import java.lang.reflect.Array;
41import java.lang.reflect.Field;
42import java.util.Arrays;
43import java.util.function.BinaryOperator;
44import 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 */
54public 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