1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Written by Doug Lea with assistance from members of JCP JSR-166
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Expert Group and released to the public domain, as explained at
4a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson * http://creativecommons.org/publicdomain/zero/1.0/
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.util.concurrent.atomic;
8a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
9a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilsonimport java.lang.reflect.Array;
10e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniakimport java.util.Arrays;
11e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniakimport java.util.function.BinaryOperator;
12e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniakimport java.util.function.UnaryOperator;
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * An array of object references in which elements may be updated
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * atomically.  See the {@link java.util.concurrent.atomic} package
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specification for description of the properties of atomic
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * variables.
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @since 1.5
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @author Doug Lea
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param <E> The base class of elements held in this array
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
23bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilsonpublic class AtomicReferenceArray<E> implements java.io.Serializable {
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final long serialVersionUID = -6209656149925076980L;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
26e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
27e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    private static final long ARRAY;
28e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    private static final int ABASE;
29e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    private static final int ASHIFT;
30a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    private final Object[] array; // must have exact type Object[]
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
328eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilson    static {
33a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        try {
34e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak            ARRAY = U.objectFieldOffset
35a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson                (AtomicReferenceArray.class.getDeclaredField("array"));
36e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak            ABASE = U.arrayBaseOffset(Object[].class);
37e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak            int scale = U.arrayIndexScale(Object[].class);
3891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle            if ((scale & (scale - 1)) != 0)
39e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak                throw new Error("array index scale not a power of two");
40e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak            ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
41e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        } catch (ReflectiveOperationException e) {
42a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson            throw new Error(e);
43a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        }
448eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilson    }
458eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilson
466232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson    private long checkedByteOffset(int i) {
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (i < 0 || i >= array.length)
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IndexOutOfBoundsException("index " + i);
496232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson
506232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson        return byteOffset(i);
516232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson    }
526232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson
536232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson    private static long byteOffset(int i) {
54e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        return ((long) i << ASHIFT) + ABASE;
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
586232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     * Creates a new AtomicReferenceArray of the given length, with all
59a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * elements initially null.
606232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     *
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param length the length of the array
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public AtomicReferenceArray(int length) {
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        array = new Object[length];
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
68bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * Creates a new AtomicReferenceArray with the same length as, and
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * all elements copied from, the given array.
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param array the array to copy elements from
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException if array is null
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public AtomicReferenceArray(E[] array) {
756232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson        // Visibility guaranteed by final field guarantees
76a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        this.array = Arrays.copyOf(array, array.length, Object[].class);
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the length of the array.
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the length of the array
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final int length() {
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return array.length;
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
89bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * Gets the current value at position {@code i}.
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param i the index
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the current value
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final E get(int i) {
956232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson        return getRaw(checkedByteOffset(i));
966232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson    }
976232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson
9891770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle    @SuppressWarnings("unchecked")
996232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson    private E getRaw(long offset) {
100e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        return (E) U.getObjectVolatile(array, offset);
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
102bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
104bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * Sets the element at position {@code i} to the given value.
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param i the index
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param newValue the new value
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final void set(int i, E newValue) {
110e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        U.putObjectVolatile(array, checkedByteOffset(i), newValue);
1116232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson    }
1126232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson
1136232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson    /**
1146232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     * Eventually sets the element at position {@code i} to the given value.
1156232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     *
1166232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     * @param i the index
1176232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     * @param newValue the new value
1186232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     * @since 1.6
1196232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     */
1206232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson    public final void lazySet(int i, E newValue) {
121e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        U.putOrderedObject(array, checkedByteOffset(i), newValue);
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
123bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
125bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * Atomically sets the element at position {@code i} to the given
126bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * value and returns the old value.
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param i the index
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param newValue the new value
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the previous value
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
132e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    @SuppressWarnings("unchecked")
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final E getAndSet(int i, E newValue) {
134e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        return (E)U.getAndSetObject(array, checkedByteOffset(i), newValue);
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
136bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
138bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * Atomically sets the element at position {@code i} to the given
139bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * updated value if the current value {@code ==} the expected value.
1406232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     *
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param i the index
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param expect the expected value
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param update the new value
144e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @return {@code true} if successful. False return indicates that
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the actual value was not equal to the expected value.
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final boolean compareAndSet(int i, E expect, E update) {
1486232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson        return compareAndSetRaw(checkedByteOffset(i), expect, update);
1496232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson    }
1506232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson
1516232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson    private boolean compareAndSetRaw(long offset, E expect, E update) {
152e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        return U.compareAndSwapObject(array, offset, expect, update);
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
156bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * Atomically sets the element at position {@code i} to the given
157bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     * updated value if the current value {@code ==} the expected value.
158bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     *
15991770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * <p><a href="package-summary.html#weakCompareAndSet">May fail
16091770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * spuriously and does not provide ordering guarantees</a>, so is
16191770798d8b9280d48d30df2ed7f63b3ed9b036fCalin Juravle     * only rarely an appropriate alternative to {@code compareAndSet}.
162bba8d1acd6dfff06c94d761c67a30154ca5ca5dfJesse Wilson     *
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param i the index
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param expect the expected value
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param update the new value
166e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @return {@code true} if successful
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final boolean weakCompareAndSet(int i, E expect, E update) {
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return compareAndSet(i, expect, update);
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
173e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * Atomically updates the element at index {@code i} with the results
174e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * of applying the given function, returning the previous value. The
175e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * function should be side-effect-free, since it may be re-applied
176e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * when attempted updates fail due to contention among threads.
177e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     *
178e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @param i the index
179e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @param updateFunction a side-effect-free function
180e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @return the previous value
181e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @since 1.8
182e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     */
183e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    public final E getAndUpdate(int i, UnaryOperator<E> updateFunction) {
184e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        long offset = checkedByteOffset(i);
185e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        E prev, next;
186e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        do {
187e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak            prev = getRaw(offset);
188e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak            next = updateFunction.apply(prev);
189e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        } while (!compareAndSetRaw(offset, prev, next));
190e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        return prev;
191e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    }
192e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak
193e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    /**
194e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * Atomically updates the element at index {@code i} with the results
195e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * of applying the given function, returning the updated value. The
196e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * function should be side-effect-free, since it may be re-applied
197e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * when attempted updates fail due to contention among threads.
198e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     *
199e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @param i the index
200e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @param updateFunction a side-effect-free function
201e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @return the updated value
202e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @since 1.8
203e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     */
204e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    public final E updateAndGet(int i, UnaryOperator<E> updateFunction) {
205e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        long offset = checkedByteOffset(i);
206e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        E prev, next;
207e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        do {
208e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak            prev = getRaw(offset);
209e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak            next = updateFunction.apply(prev);
210e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        } while (!compareAndSetRaw(offset, prev, next));
211e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        return next;
212e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    }
213e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak
214e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    /**
215e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * Atomically updates the element at index {@code i} with the
216e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * results of applying the given function to the current and
217e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * given values, returning the previous value. The function should
218e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * be side-effect-free, since it may be re-applied when attempted
219e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * updates fail due to contention among threads.  The function is
220e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * applied with the current value at index {@code i} as its first
221e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * argument, and the given update as the second argument.
222e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     *
223e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @param i the index
224e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @param x the update value
225e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @param accumulatorFunction a side-effect-free function of two arguments
226e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @return the previous value
227e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @since 1.8
228e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     */
229e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    public final E getAndAccumulate(int i, E x,
230e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak                                    BinaryOperator<E> accumulatorFunction) {
231e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        long offset = checkedByteOffset(i);
232e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        E prev, next;
233e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        do {
234e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak            prev = getRaw(offset);
235e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak            next = accumulatorFunction.apply(prev, x);
236e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        } while (!compareAndSetRaw(offset, prev, next));
237e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        return prev;
238e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    }
239e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak
240e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    /**
241e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * Atomically updates the element at index {@code i} with the
242e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * results of applying the given function to the current and
243e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * given values, returning the updated value. The function should
244e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * be side-effect-free, since it may be re-applied when attempted
245e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * updates fail due to contention among threads.  The function is
246e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * applied with the current value at index {@code i} as its first
247e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * argument, and the given update as the second argument.
248e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     *
249e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @param i the index
250e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @param x the update value
251e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @param accumulatorFunction a side-effect-free function of two arguments
252e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @return the updated value
253e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @since 1.8
254e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     */
255e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    public final E accumulateAndGet(int i, E x,
256e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak                                    BinaryOperator<E> accumulatorFunction) {
257e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        long offset = checkedByteOffset(i);
258e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        E prev, next;
259e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        do {
260e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak            prev = getRaw(offset);
261e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak            next = accumulatorFunction.apply(prev, x);
262e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        } while (!compareAndSetRaw(offset, prev, next));
263e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        return next;
264e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    }
265e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak
266e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak    /**
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the String representation of the current values of array.
2686232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson     * @return the String representation of the current values of array
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String toString() {
271a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        int iMax = array.length - 1;
2726232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson        if (iMax == -1)
2736232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson            return "[]";
2746232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson
2756232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson        StringBuilder b = new StringBuilder();
2766232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson        b.append('[');
2776232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson        for (int i = 0; ; i++) {
2786232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson            b.append(getRaw(byteOffset(i)));
2796232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson            if (i == iMax)
2806232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson                return b.append(']').toString();
2818eb35c835be1345d3873a82cc9e42f944d698afdJesse Wilson            b.append(',').append(' ');
2826232a5efed0ea103e35aec73206e5e03a8b82e0cJesse Wilson        }
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
285a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    /**
286a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     * Reconstitutes the instance from a stream (that is, deserializes it).
287e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @param s the stream
288e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @throws ClassNotFoundException if the class of a serialized object
289e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     *         could not be found
290e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak     * @throws java.io.IOException if an I/O error occurs
291a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson     */
292a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    private void readObject(java.io.ObjectInputStream s)
293e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        throws java.io.IOException, ClassNotFoundException {
294a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        // Note: This must be changed if any additional fields are defined
295a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        Object a = s.readFields().get("array", null);
296a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        if (a == null || !a.getClass().isArray())
297a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson            throw new java.io.InvalidObjectException("Not array type");
298a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson        if (a.getClass() != Object[].class)
299a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson            a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class);
300e8b323c7cb7d55be9a4df579231e44f04f53d766Przemyslaw Szczepaniak        U.putObjectVolatile(this, ARRAY, a);
301a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson    }
302a807b4d808d2591894daf13aab179b2e9c46a2f5Jesse Wilson
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
304