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