jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java
changeset 11892 1b260c532b70
parent 9242 ef138d47df58
child 11902 a94ba35d9c4a
equal deleted inserted replaced
10916:5a763073fa37 11892:1b260c532b70
    32  * Expert Group and released to the public domain, as explained at
    32  * Expert Group and released to the public domain, as explained at
    33  * http://creativecommons.org/publicdomain/zero/1.0/
    33  * http://creativecommons.org/publicdomain/zero/1.0/
    34  */
    34  */
    35 
    35 
    36 package java.util.concurrent.atomic;
    36 package java.util.concurrent.atomic;
       
    37 
       
    38 import java.lang.reflect.Array;
       
    39 import java.util.Arrays;
    37 import sun.misc.Unsafe;
    40 import sun.misc.Unsafe;
    38 import java.util.*;
       
    39 
    41 
    40 /**
    42 /**
    41  * An array of object references in which elements may be updated
    43  * An array of object references in which elements may be updated
    42  * atomically.  See the {@link java.util.concurrent.atomic} package
    44  * atomically.  See the {@link java.util.concurrent.atomic} package
    43  * specification for description of the properties of atomic
    45  * specification for description of the properties of atomic
    47  * @param <E> The base class of elements held in this array
    49  * @param <E> The base class of elements held in this array
    48  */
    50  */
    49 public class AtomicReferenceArray<E> implements java.io.Serializable {
    51 public class AtomicReferenceArray<E> implements java.io.Serializable {
    50     private static final long serialVersionUID = -6209656149925076980L;
    52     private static final long serialVersionUID = -6209656149925076980L;
    51 
    53 
    52     private static final Unsafe unsafe = Unsafe.getUnsafe();
    54     private static final Unsafe unsafe;
    53     private static final int base = unsafe.arrayBaseOffset(Object[].class);
    55     private static final int base;
    54     private static final int shift;
    56     private static final int shift;
    55     private final Object[] array;
    57     private static final long arrayFieldOffset;
       
    58     private final Object[] array; // must have exact type Object[]
    56 
    59 
    57     static {
    60     static {
    58         int scale = unsafe.arrayIndexScale(Object[].class);
    61         int scale;
       
    62         try {
       
    63             unsafe = Unsafe.getUnsafe();
       
    64             arrayFieldOffset = unsafe.objectFieldOffset
       
    65                 (AtomicReferenceArray.class.getDeclaredField("array"));
       
    66             base = unsafe.arrayBaseOffset(Object[].class);
       
    67             scale = unsafe.arrayIndexScale(Object[].class);
       
    68         } catch (Exception e) {
       
    69             throw new Error(e);
       
    70         }
    59         if ((scale & (scale - 1)) != 0)
    71         if ((scale & (scale - 1)) != 0)
    60             throw new Error("data type scale not a power of two");
    72             throw new Error("data type scale not a power of two");
    61         shift = 31 - Integer.numberOfLeadingZeros(scale);
    73         shift = 31 - Integer.numberOfLeadingZeros(scale);
    62     }
    74     }
    63 
    75 
    89      * @param array the array to copy elements from
   101      * @param array the array to copy elements from
    90      * @throws NullPointerException if array is null
   102      * @throws NullPointerException if array is null
    91      */
   103      */
    92     public AtomicReferenceArray(E[] array) {
   104     public AtomicReferenceArray(E[] array) {
    93         // Visibility guaranteed by final field guarantees
   105         // Visibility guaranteed by final field guarantees
    94         this.array = array.clone();
   106         this.array = Arrays.copyOf(array, array.length, Object[].class);
    95     }
   107     }
    96 
   108 
    97     /**
   109     /**
    98      * Returns the length of the array.
   110      * Returns the length of the array.
    99      *
   111      *
   148      * @return the previous value
   160      * @return the previous value
   149      */
   161      */
   150     public final E getAndSet(int i, E newValue) {
   162     public final E getAndSet(int i, E newValue) {
   151         long offset = checkedByteOffset(i);
   163         long offset = checkedByteOffset(i);
   152         while (true) {
   164         while (true) {
   153             E current = (E) getRaw(offset);
   165             E current = getRaw(offset);
   154             if (compareAndSetRaw(offset, current, newValue))
   166             if (compareAndSetRaw(offset, current, newValue))
   155                 return current;
   167                 return current;
   156         }
   168         }
   157     }
   169     }
   158 
   170 
   194     /**
   206     /**
   195      * Returns the String representation of the current values of array.
   207      * Returns the String representation of the current values of array.
   196      * @return the String representation of the current values of array
   208      * @return the String representation of the current values of array
   197      */
   209      */
   198     public String toString() {
   210     public String toString() {
   199            int iMax = array.length - 1;
   211         int iMax = array.length - 1;
   200         if (iMax == -1)
   212         if (iMax == -1)
   201             return "[]";
   213             return "[]";
   202 
   214 
   203         StringBuilder b = new StringBuilder();
   215         StringBuilder b = new StringBuilder();
   204         b.append('[');
   216         b.append('[');
   208                 return b.append(']').toString();
   220                 return b.append(']').toString();
   209             b.append(',').append(' ');
   221             b.append(',').append(' ');
   210         }
   222         }
   211     }
   223     }
   212 
   224 
       
   225     /**
       
   226      * Reconstitutes the instance from a stream (that is, deserializes it).
       
   227      * @param s the stream
       
   228      */
       
   229     private void readObject(java.io.ObjectInputStream s)
       
   230         throws java.io.IOException, ClassNotFoundException {
       
   231         // Note: This must be changed if any additional fields are defined
       
   232         Object a = s.readFields().get("array", null);
       
   233         if (a == null || !a.getClass().isArray())
       
   234             throw new java.io.InvalidObjectException("Not array type");
       
   235         if (a.getClass() != Object[].class)
       
   236             a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class);
       
   237         unsafe.putObjectVolatile(this, arrayFieldOffset, a);
       
   238     }
       
   239 
   213 }
   240 }