src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java

Print this page




  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  * Written by Doug Lea with assistance from members of JCP JSR-166
  28  * Expert Group.  Adapted and released, under explicit permission,
  29  * from JDK ArrayList.java which carries the following copyright:
  30  *
  31  * Copyright 1997 by Sun Microsystems, Inc.,
  32  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  33  * All rights reserved.
  34  */
  35 
  36 package java.util.concurrent;
  37 import java.util.*;
  38 import java.util.concurrent.locks.*;
  39 import sun.misc.Unsafe;
  40 
  41 /**
  42  * A thread-safe variant of {@link java.util.ArrayList} in which all mutative
  43  * operations (<tt>add</tt>, <tt>set</tt>, and so on) are implemented by
  44  * making a fresh copy of the underlying array.
  45  *
  46  * <p> This is ordinarily too costly, but may be <em>more</em> efficient
  47  * than alternatives when traversal operations vastly outnumber
  48  * mutations, and is useful when you cannot or don't want to
  49  * synchronize traversals, yet need to preclude interference among
  50  * concurrent threads.  The "snapshot" style iterator method uses a
  51  * reference to the state of the array at the point that the iterator
  52  * was created. This array never changes during the lifetime of the
  53  * iterator, so interference is impossible and the iterator is
  54  * guaranteed not to throw <tt>ConcurrentModificationException</tt>.
  55  * The iterator will not reflect additions, removals, or changes to
  56  * the list since the iterator was created.  Element-changing
  57  * operations on iterators themselves (<tt>remove</tt>, <tt>set</tt>, and
  58  * <tt>add</tt>) are not supported. These methods throw
  59  * <tt>UnsupportedOperationException</tt>.


 264      * @param index index to start searching backwards from
 265      * @return the index of the last occurrence of the element at position
 266      *         less than or equal to <tt>index</tt> in this list;
 267      *         -1 if the element is not found.
 268      * @throws IndexOutOfBoundsException if the specified index is greater
 269      *         than or equal to the current size of this list
 270      */
 271     public int lastIndexOf(E e, int index) {
 272         Object[] elements = getArray();
 273         return lastIndexOf(e, elements, index);
 274     }
 275 
 276     /**
 277      * Returns a shallow copy of this list.  (The elements themselves
 278      * are not copied.)
 279      *
 280      * @return a clone of this list
 281      */
 282     public Object clone() {
 283         try {
 284             CopyOnWriteArrayList c = (CopyOnWriteArrayList)(super.clone());
 285             c.resetLock();
 286             return c;


 287         } catch (CloneNotSupportedException e) {
 288             // this shouldn't happen, since we are Cloneable
 289             throw new InternalError();
 290         }
 291     }
 292 
 293     /**
 294      * Returns an array containing all of the elements in this list
 295      * in proper sequence (from first to last element).
 296      *
 297      * <p>The returned array will be "safe" in that no references to it are
 298      * maintained by this list.  (In other words, this method must allocate
 299      * a new array).  The caller is thus free to modify the returned array.
 300      *
 301      * <p>This method acts as bridge between array-based and collection-based
 302      * APIs.
 303      *
 304      * @return an array containing all the elements in this list
 305      */
 306     public Object[] toArray() {


1313         }
1314 
1315         public void set(E e) {
1316             throw new UnsupportedOperationException();
1317         }
1318 
1319         public void add(E e) {
1320             throw new UnsupportedOperationException();
1321         }
1322     }
1323 
1324     // Support for resetting lock while deserializing
1325     private void resetLock() {
1326         UNSAFE.putObjectVolatile(this, lockOffset, new ReentrantLock());
1327     }
1328     private static final sun.misc.Unsafe UNSAFE;
1329     private static final long lockOffset;
1330     static {
1331         try {
1332             UNSAFE = sun.misc.Unsafe.getUnsafe();
1333             Class k = CopyOnWriteArrayList.class;
1334             lockOffset = UNSAFE.objectFieldOffset
1335                 (k.getDeclaredField("lock"));
1336         } catch (Exception e) {
1337             throw new Error(e);
1338         }
1339     }
1340 }


  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  * Written by Doug Lea with assistance from members of JCP JSR-166
  28  * Expert Group.  Adapted and released, under explicit permission,
  29  * from JDK ArrayList.java which carries the following copyright:
  30  *
  31  * Copyright 1997 by Sun Microsystems, Inc.,
  32  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  33  * All rights reserved.
  34  */
  35 
  36 package java.util.concurrent;
  37 import java.util.*;
  38 import java.util.concurrent.locks.*;

  39 
  40 /**
  41  * A thread-safe variant of {@link java.util.ArrayList} in which all mutative
  42  * operations (<tt>add</tt>, <tt>set</tt>, and so on) are implemented by
  43  * making a fresh copy of the underlying array.
  44  *
  45  * <p> This is ordinarily too costly, but may be <em>more</em> efficient
  46  * than alternatives when traversal operations vastly outnumber
  47  * mutations, and is useful when you cannot or don't want to
  48  * synchronize traversals, yet need to preclude interference among
  49  * concurrent threads.  The "snapshot" style iterator method uses a
  50  * reference to the state of the array at the point that the iterator
  51  * was created. This array never changes during the lifetime of the
  52  * iterator, so interference is impossible and the iterator is
  53  * guaranteed not to throw <tt>ConcurrentModificationException</tt>.
  54  * The iterator will not reflect additions, removals, or changes to
  55  * the list since the iterator was created.  Element-changing
  56  * operations on iterators themselves (<tt>remove</tt>, <tt>set</tt>, and
  57  * <tt>add</tt>) are not supported. These methods throw
  58  * <tt>UnsupportedOperationException</tt>.


 263      * @param index index to start searching backwards from
 264      * @return the index of the last occurrence of the element at position
 265      *         less than or equal to <tt>index</tt> in this list;
 266      *         -1 if the element is not found.
 267      * @throws IndexOutOfBoundsException if the specified index is greater
 268      *         than or equal to the current size of this list
 269      */
 270     public int lastIndexOf(E e, int index) {
 271         Object[] elements = getArray();
 272         return lastIndexOf(e, elements, index);
 273     }
 274 
 275     /**
 276      * Returns a shallow copy of this list.  (The elements themselves
 277      * are not copied.)
 278      *
 279      * @return a clone of this list
 280      */
 281     public Object clone() {
 282         try {
 283             @SuppressWarnings("unchecked")
 284             CopyOnWriteArrayList<E> clone =
 285                 (CopyOnWriteArrayList<E>) super.clone();
 286             clone.resetLock();
 287             return clone;
 288         } catch (CloneNotSupportedException e) {
 289             // this shouldn't happen, since we are Cloneable
 290             throw new InternalError();
 291         }
 292     }
 293 
 294     /**
 295      * Returns an array containing all of the elements in this list
 296      * in proper sequence (from first to last element).
 297      *
 298      * <p>The returned array will be "safe" in that no references to it are
 299      * maintained by this list.  (In other words, this method must allocate
 300      * a new array).  The caller is thus free to modify the returned array.
 301      *
 302      * <p>This method acts as bridge between array-based and collection-based
 303      * APIs.
 304      *
 305      * @return an array containing all the elements in this list
 306      */
 307     public Object[] toArray() {


1314         }
1315 
1316         public void set(E e) {
1317             throw new UnsupportedOperationException();
1318         }
1319 
1320         public void add(E e) {
1321             throw new UnsupportedOperationException();
1322         }
1323     }
1324 
1325     // Support for resetting lock while deserializing
1326     private void resetLock() {
1327         UNSAFE.putObjectVolatile(this, lockOffset, new ReentrantLock());
1328     }
1329     private static final sun.misc.Unsafe UNSAFE;
1330     private static final long lockOffset;
1331     static {
1332         try {
1333             UNSAFE = sun.misc.Unsafe.getUnsafe();
1334             Class<?> k = CopyOnWriteArrayList.class;
1335             lockOffset = UNSAFE.objectFieldOffset
1336                 (k.getDeclaredField("lock"));
1337         } catch (Exception e) {
1338             throw new Error(e);
1339         }
1340     }
1341 }