rt/emul/compact/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 19 Mar 2016 12:51:03 +0100
changeset 1895 bfaf3300b7ba
parent 1890 212417b74b72
permissions -rw-r--r--
Making java.util.concurrent package compilable except ForkJoinPool
     1 /*
     2  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    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>.
    59  *
    60  * <p>All elements are permitted, including <tt>null</tt>.
    61  *
    62  * <p>Memory consistency effects: As with other concurrent
    63  * collections, actions in a thread prior to placing an object into a
    64  * {@code CopyOnWriteArrayList}
    65  * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
    66  * actions subsequent to the access or removal of that element from
    67  * the {@code CopyOnWriteArrayList} in another thread.
    68  *
    69  * <p>This class is a member of the
    70  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
    71  * Java Collections Framework</a>.
    72  *
    73  * @since 1.5
    74  * @author Doug Lea
    75  * @param <E> the type of elements held in this collection
    76  */
    77 public class CopyOnWriteArrayList<E>
    78     implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    79     private static final long serialVersionUID = 8673264195747942595L;
    80 
    81     /** The lock protecting all mutators */
    82     transient ReentrantLock lock = new ReentrantLock();
    83 
    84     /** The array, accessed only via getArray/setArray. */
    85     private volatile transient Object[] array;
    86 
    87     /**
    88      * Gets the array.  Non-private so as to also be accessible
    89      * from CopyOnWriteArraySet class.
    90      */
    91     final Object[] getArray() {
    92         return array;
    93     }
    94 
    95     /**
    96      * Sets the array.
    97      */
    98     final void setArray(Object[] a) {
    99         array = a;
   100     }
   101 
   102     /**
   103      * Creates an empty list.
   104      */
   105     public CopyOnWriteArrayList() {
   106         setArray(new Object[0]);
   107     }
   108 
   109     /**
   110      * Creates a list containing the elements of the specified
   111      * collection, in the order they are returned by the collection's
   112      * iterator.
   113      *
   114      * @param c the collection of initially held elements
   115      * @throws NullPointerException if the specified collection is null
   116      */
   117     public CopyOnWriteArrayList(Collection<? extends E> c) {
   118         Object[] elements = c.toArray();
   119         // c.toArray might (incorrectly) not return Object[] (see 6260652)
   120         if (elements.getClass() != Object[].class)
   121             elements = Arrays.copyOf(elements, elements.length, Object[].class);
   122         setArray(elements);
   123     }
   124 
   125     /**
   126      * Creates a list holding a copy of the given array.
   127      *
   128      * @param toCopyIn the array (a copy of this array is used as the
   129      *        internal array)
   130      * @throws NullPointerException if the specified array is null
   131      */
   132     public CopyOnWriteArrayList(E[] toCopyIn) {
   133         setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
   134     }
   135 
   136     /**
   137      * Returns the number of elements in this list.
   138      *
   139      * @return the number of elements in this list
   140      */
   141     public int size() {
   142         return getArray().length;
   143     }
   144 
   145     /**
   146      * Returns <tt>true</tt> if this list contains no elements.
   147      *
   148      * @return <tt>true</tt> if this list contains no elements
   149      */
   150     public boolean isEmpty() {
   151         return size() == 0;
   152     }
   153 
   154     /**
   155      * Test for equality, coping with nulls.
   156      */
   157     private static boolean eq(Object o1, Object o2) {
   158         return (o1 == null ? o2 == null : o1.equals(o2));
   159     }
   160 
   161     /**
   162      * static version of indexOf, to allow repeated calls without
   163      * needing to re-acquire array each time.
   164      * @param o element to search for
   165      * @param elements the array
   166      * @param index first index to search
   167      * @param fence one past last index to search
   168      * @return index of element, or -1 if absent
   169      */
   170     private static int indexOf(Object o, Object[] elements,
   171                                int index, int fence) {
   172         if (o == null) {
   173             for (int i = index; i < fence; i++)
   174                 if (elements[i] == null)
   175                     return i;
   176         } else {
   177             for (int i = index; i < fence; i++)
   178                 if (o.equals(elements[i]))
   179                     return i;
   180         }
   181         return -1;
   182     }
   183 
   184     /**
   185      * static version of lastIndexOf.
   186      * @param o element to search for
   187      * @param elements the array
   188      * @param index first index to search
   189      * @return index of element, or -1 if absent
   190      */
   191     private static int lastIndexOf(Object o, Object[] elements, int index) {
   192         if (o == null) {
   193             for (int i = index; i >= 0; i--)
   194                 if (elements[i] == null)
   195                     return i;
   196         } else {
   197             for (int i = index; i >= 0; i--)
   198                 if (o.equals(elements[i]))
   199                     return i;
   200         }
   201         return -1;
   202     }
   203 
   204     /**
   205      * Returns <tt>true</tt> if this list contains the specified element.
   206      * More formally, returns <tt>true</tt> if and only if this list contains
   207      * at least one element <tt>e</tt> such that
   208      * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
   209      *
   210      * @param o element whose presence in this list is to be tested
   211      * @return <tt>true</tt> if this list contains the specified element
   212      */
   213     public boolean contains(Object o) {
   214         Object[] elements = getArray();
   215         return indexOf(o, elements, 0, elements.length) >= 0;
   216     }
   217 
   218     /**
   219      * {@inheritDoc}
   220      */
   221     public int indexOf(Object o) {
   222         Object[] elements = getArray();
   223         return indexOf(o, elements, 0, elements.length);
   224     }
   225 
   226     /**
   227      * Returns the index of the first occurrence of the specified element in
   228      * this list, searching forwards from <tt>index</tt>, or returns -1 if
   229      * the element is not found.
   230      * More formally, returns the lowest index <tt>i</tt> such that
   231      * <tt>(i&nbsp;&gt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(e==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;e.equals(get(i))))</tt>,
   232      * or -1 if there is no such index.
   233      *
   234      * @param e element to search for
   235      * @param index index to start searching from
   236      * @return the index of the first occurrence of the element in
   237      *         this list at position <tt>index</tt> or later in the list;
   238      *         <tt>-1</tt> if the element is not found.
   239      * @throws IndexOutOfBoundsException if the specified index is negative
   240      */
   241     public int indexOf(E e, int index) {
   242         Object[] elements = getArray();
   243         return indexOf(e, elements, index, elements.length);
   244     }
   245 
   246     /**
   247      * {@inheritDoc}
   248      */
   249     public int lastIndexOf(Object o) {
   250         Object[] elements = getArray();
   251         return lastIndexOf(o, elements, elements.length - 1);
   252     }
   253 
   254     /**
   255      * Returns the index of the last occurrence of the specified element in
   256      * this list, searching backwards from <tt>index</tt>, or returns -1 if
   257      * the element is not found.
   258      * More formally, returns the highest index <tt>i</tt> such that
   259      * <tt>(i&nbsp;&lt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(e==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;e.equals(get(i))))</tt>,
   260      * or -1 if there is no such index.
   261      *
   262      * @param e element to search for
   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             CopyOnWriteArrayList c = (CopyOnWriteArrayList)(super.clone());
   284             c.resetLock();
   285             return c;
   286         } catch (CloneNotSupportedException e) {
   287             // this shouldn't happen, since we are Cloneable
   288             throw new InternalError();
   289         }
   290     }
   291 
   292     /**
   293      * Returns an array containing all of the elements in this list
   294      * in proper sequence (from first to last element).
   295      *
   296      * <p>The returned array will be "safe" in that no references to it are
   297      * maintained by this list.  (In other words, this method must allocate
   298      * a new array).  The caller is thus free to modify the returned array.
   299      *
   300      * <p>This method acts as bridge between array-based and collection-based
   301      * APIs.
   302      *
   303      * @return an array containing all the elements in this list
   304      */
   305     public Object[] toArray() {
   306         Object[] elements = getArray();
   307         return Arrays.copyOf(elements, elements.length);
   308     }
   309 
   310     /**
   311      * Returns an array containing all of the elements in this list in
   312      * proper sequence (from first to last element); the runtime type of
   313      * the returned array is that of the specified array.  If the list fits
   314      * in the specified array, it is returned therein.  Otherwise, a new
   315      * array is allocated with the runtime type of the specified array and
   316      * the size of this list.
   317      *
   318      * <p>If this list fits in the specified array with room to spare
   319      * (i.e., the array has more elements than this list), the element in
   320      * the array immediately following the end of the list is set to
   321      * <tt>null</tt>.  (This is useful in determining the length of this
   322      * list <i>only</i> if the caller knows that this list does not contain
   323      * any null elements.)
   324      *
   325      * <p>Like the {@link #toArray()} method, this method acts as bridge between
   326      * array-based and collection-based APIs.  Further, this method allows
   327      * precise control over the runtime type of the output array, and may,
   328      * under certain circumstances, be used to save allocation costs.
   329      *
   330      * <p>Suppose <tt>x</tt> is a list known to contain only strings.
   331      * The following code can be used to dump the list into a newly
   332      * allocated array of <tt>String</tt>:
   333      *
   334      * <pre>
   335      *     String[] y = x.toArray(new String[0]);</pre>
   336      *
   337      * Note that <tt>toArray(new Object[0])</tt> is identical in function to
   338      * <tt>toArray()</tt>.
   339      *
   340      * @param a the array into which the elements of the list are to
   341      *          be stored, if it is big enough; otherwise, a new array of the
   342      *          same runtime type is allocated for this purpose.
   343      * @return an array containing all the elements in this list
   344      * @throws ArrayStoreException if the runtime type of the specified array
   345      *         is not a supertype of the runtime type of every element in
   346      *         this list
   347      * @throws NullPointerException if the specified array is null
   348      */
   349     @SuppressWarnings("unchecked")
   350     public <T> T[] toArray(T a[]) {
   351         Object[] elements = getArray();
   352         int len = elements.length;
   353         if (a.length < len)
   354             return (T[]) Arrays.copyOf(elements, len, a.getClass());
   355         else {
   356             System.arraycopy(elements, 0, a, 0, len);
   357             if (a.length > len)
   358                 a[len] = null;
   359             return a;
   360         }
   361     }
   362 
   363     // Positional Access Operations
   364 
   365     @SuppressWarnings("unchecked")
   366     private E get(Object[] a, int index) {
   367         return (E) a[index];
   368     }
   369 
   370     /**
   371      * {@inheritDoc}
   372      *
   373      * @throws IndexOutOfBoundsException {@inheritDoc}
   374      */
   375     public E get(int index) {
   376         return get(getArray(), index);
   377     }
   378 
   379     /**
   380      * Replaces the element at the specified position in this list with the
   381      * specified element.
   382      *
   383      * @throws IndexOutOfBoundsException {@inheritDoc}
   384      */
   385     public E set(int index, E element) {
   386         final ReentrantLock lock = this.lock;
   387         lock.lock();
   388         try {
   389             Object[] elements = getArray();
   390             E oldValue = get(elements, index);
   391 
   392             if (oldValue != element) {
   393                 int len = elements.length;
   394                 Object[] newElements = Arrays.copyOf(elements, len);
   395                 newElements[index] = element;
   396                 setArray(newElements);
   397             } else {
   398                 // Not quite a no-op; ensures volatile write semantics
   399                 setArray(elements);
   400             }
   401             return oldValue;
   402         } finally {
   403             lock.unlock();
   404         }
   405     }
   406 
   407     /**
   408      * Appends the specified element to the end of this list.
   409      *
   410      * @param e element to be appended to this list
   411      * @return <tt>true</tt> (as specified by {@link Collection#add})
   412      */
   413     public boolean add(E e) {
   414         final ReentrantLock lock = this.lock;
   415         lock.lock();
   416         try {
   417             Object[] elements = getArray();
   418             int len = elements.length;
   419             Object[] newElements = Arrays.copyOf(elements, len + 1);
   420             newElements[len] = e;
   421             setArray(newElements);
   422             return true;
   423         } finally {
   424             lock.unlock();
   425         }
   426     }
   427 
   428     /**
   429      * Inserts the specified element at the specified position in this
   430      * list. Shifts the element currently at that position (if any) and
   431      * any subsequent elements to the right (adds one to their indices).
   432      *
   433      * @throws IndexOutOfBoundsException {@inheritDoc}
   434      */
   435     public void add(int index, E element) {
   436         final ReentrantLock lock = this.lock;
   437         lock.lock();
   438         try {
   439             Object[] elements = getArray();
   440             int len = elements.length;
   441             if (index > len || index < 0)
   442                 throw new IndexOutOfBoundsException("Index: "+index+
   443                                                     ", Size: "+len);
   444             Object[] newElements;
   445             int numMoved = len - index;
   446             if (numMoved == 0)
   447                 newElements = Arrays.copyOf(elements, len + 1);
   448             else {
   449                 newElements = new Object[len + 1];
   450                 System.arraycopy(elements, 0, newElements, 0, index);
   451                 System.arraycopy(elements, index, newElements, index + 1,
   452                                  numMoved);
   453             }
   454             newElements[index] = element;
   455             setArray(newElements);
   456         } finally {
   457             lock.unlock();
   458         }
   459     }
   460 
   461     /**
   462      * Removes the element at the specified position in this list.
   463      * Shifts any subsequent elements to the left (subtracts one from their
   464      * indices).  Returns the element that was removed from the list.
   465      *
   466      * @throws IndexOutOfBoundsException {@inheritDoc}
   467      */
   468     public E remove(int index) {
   469         final ReentrantLock lock = this.lock;
   470         lock.lock();
   471         try {
   472             Object[] elements = getArray();
   473             int len = elements.length;
   474             E oldValue = get(elements, index);
   475             int numMoved = len - index - 1;
   476             if (numMoved == 0)
   477                 setArray(Arrays.copyOf(elements, len - 1));
   478             else {
   479                 Object[] newElements = new Object[len - 1];
   480                 System.arraycopy(elements, 0, newElements, 0, index);
   481                 System.arraycopy(elements, index + 1, newElements, index,
   482                                  numMoved);
   483                 setArray(newElements);
   484             }
   485             return oldValue;
   486         } finally {
   487             lock.unlock();
   488         }
   489     }
   490 
   491     /**
   492      * Removes the first occurrence of the specified element from this list,
   493      * if it is present.  If this list does not contain the element, it is
   494      * unchanged.  More formally, removes the element with the lowest index
   495      * <tt>i</tt> such that
   496      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
   497      * (if such an element exists).  Returns <tt>true</tt> if this list
   498      * contained the specified element (or equivalently, if this list
   499      * changed as a result of the call).
   500      *
   501      * @param o element to be removed from this list, if present
   502      * @return <tt>true</tt> if this list contained the specified element
   503      */
   504     public boolean remove(Object o) {
   505         final ReentrantLock lock = this.lock;
   506         lock.lock();
   507         try {
   508             Object[] elements = getArray();
   509             int len = elements.length;
   510             if (len != 0) {
   511                 // Copy while searching for element to remove
   512                 // This wins in the normal case of element being present
   513                 int newlen = len - 1;
   514                 Object[] newElements = new Object[newlen];
   515 
   516                 for (int i = 0; i < newlen; ++i) {
   517                     if (eq(o, elements[i])) {
   518                         // found one;  copy remaining and exit
   519                         for (int k = i + 1; k < len; ++k)
   520                             newElements[k-1] = elements[k];
   521                         setArray(newElements);
   522                         return true;
   523                     } else
   524                         newElements[i] = elements[i];
   525                 }
   526 
   527                 // special handling for last cell
   528                 if (eq(o, elements[newlen])) {
   529                     setArray(newElements);
   530                     return true;
   531                 }
   532             }
   533             return false;
   534         } finally {
   535             lock.unlock();
   536         }
   537     }
   538 
   539     /**
   540      * Removes from this list all of the elements whose index is between
   541      * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
   542      * Shifts any succeeding elements to the left (reduces their index).
   543      * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements.
   544      * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.)
   545      *
   546      * @param fromIndex index of first element to be removed
   547      * @param toIndex index after last element to be removed
   548      * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range
   549      *         ({@code{fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
   550      */
   551     private void removeRange(int fromIndex, int toIndex) {
   552         final ReentrantLock lock = this.lock;
   553         lock.lock();
   554         try {
   555             Object[] elements = getArray();
   556             int len = elements.length;
   557 
   558             if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)
   559                 throw new IndexOutOfBoundsException();
   560             int newlen = len - (toIndex - fromIndex);
   561             int numMoved = len - toIndex;
   562             if (numMoved == 0)
   563                 setArray(Arrays.copyOf(elements, newlen));
   564             else {
   565                 Object[] newElements = new Object[newlen];
   566                 System.arraycopy(elements, 0, newElements, 0, fromIndex);
   567                 System.arraycopy(elements, toIndex, newElements,
   568                                  fromIndex, numMoved);
   569                 setArray(newElements);
   570             }
   571         } finally {
   572             lock.unlock();
   573         }
   574     }
   575 
   576     /**
   577      * Append the element if not present.
   578      *
   579      * @param e element to be added to this list, if absent
   580      * @return <tt>true</tt> if the element was added
   581      */
   582     public boolean addIfAbsent(E e) {
   583         final ReentrantLock lock = this.lock;
   584         lock.lock();
   585         try {
   586             // Copy while checking if already present.
   587             // This wins in the most common case where it is not present
   588             Object[] elements = getArray();
   589             int len = elements.length;
   590             Object[] newElements = new Object[len + 1];
   591             for (int i = 0; i < len; ++i) {
   592                 if (eq(e, elements[i]))
   593                     return false; // exit, throwing away copy
   594                 else
   595                     newElements[i] = elements[i];
   596             }
   597             newElements[len] = e;
   598             setArray(newElements);
   599             return true;
   600         } finally {
   601             lock.unlock();
   602         }
   603     }
   604 
   605     /**
   606      * Returns <tt>true</tt> if this list contains all of the elements of the
   607      * specified collection.
   608      *
   609      * @param c collection to be checked for containment in this list
   610      * @return <tt>true</tt> if this list contains all of the elements of the
   611      *         specified collection
   612      * @throws NullPointerException if the specified collection is null
   613      * @see #contains(Object)
   614      */
   615     public boolean containsAll(Collection<?> c) {
   616         Object[] elements = getArray();
   617         int len = elements.length;
   618         for (Object e : c) {
   619             if (indexOf(e, elements, 0, len) < 0)
   620                 return false;
   621         }
   622         return true;
   623     }
   624 
   625     /**
   626      * Removes from this list all of its elements that are contained in
   627      * the specified collection. This is a particularly expensive operation
   628      * in this class because of the need for an internal temporary array.
   629      *
   630      * @param c collection containing elements to be removed from this list
   631      * @return <tt>true</tt> if this list changed as a result of the call
   632      * @throws ClassCastException if the class of an element of this list
   633      *         is incompatible with the specified collection
   634      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
   635      * @throws NullPointerException if this list contains a null element and the
   636      *         specified collection does not permit null elements
   637      *         (<a href="../Collection.html#optional-restrictions">optional</a>),
   638      *         or if the specified collection is null
   639      * @see #remove(Object)
   640      */
   641     public boolean removeAll(Collection<?> c) {
   642         final ReentrantLock lock = this.lock;
   643         lock.lock();
   644         try {
   645             Object[] elements = getArray();
   646             int len = elements.length;
   647             if (len != 0) {
   648                 // temp array holds those elements we know we want to keep
   649                 int newlen = 0;
   650                 Object[] temp = new Object[len];
   651                 for (int i = 0; i < len; ++i) {
   652                     Object element = elements[i];
   653                     if (!c.contains(element))
   654                         temp[newlen++] = element;
   655                 }
   656                 if (newlen != len) {
   657                     setArray(Arrays.copyOf(temp, newlen));
   658                     return true;
   659                 }
   660             }
   661             return false;
   662         } finally {
   663             lock.unlock();
   664         }
   665     }
   666 
   667     /**
   668      * Retains only the elements in this list that are contained in the
   669      * specified collection.  In other words, removes from this list all of
   670      * its elements that are not contained in the specified collection.
   671      *
   672      * @param c collection containing elements to be retained in this list
   673      * @return <tt>true</tt> if this list changed as a result of the call
   674      * @throws ClassCastException if the class of an element of this list
   675      *         is incompatible with the specified collection
   676      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
   677      * @throws NullPointerException if this list contains a null element and the
   678      *         specified collection does not permit null elements
   679      *         (<a href="../Collection.html#optional-restrictions">optional</a>),
   680      *         or if the specified collection is null
   681      * @see #remove(Object)
   682      */
   683     public boolean retainAll(Collection<?> c) {
   684         final ReentrantLock lock = this.lock;
   685         lock.lock();
   686         try {
   687             Object[] elements = getArray();
   688             int len = elements.length;
   689             if (len != 0) {
   690                 // temp array holds those elements we know we want to keep
   691                 int newlen = 0;
   692                 Object[] temp = new Object[len];
   693                 for (int i = 0; i < len; ++i) {
   694                     Object element = elements[i];
   695                     if (c.contains(element))
   696                         temp[newlen++] = element;
   697                 }
   698                 if (newlen != len) {
   699                     setArray(Arrays.copyOf(temp, newlen));
   700                     return true;
   701                 }
   702             }
   703             return false;
   704         } finally {
   705             lock.unlock();
   706         }
   707     }
   708 
   709     /**
   710      * Appends all of the elements in the specified collection that
   711      * are not already contained in this list, to the end of
   712      * this list, in the order that they are returned by the
   713      * specified collection's iterator.
   714      *
   715      * @param c collection containing elements to be added to this list
   716      * @return the number of elements added
   717      * @throws NullPointerException if the specified collection is null
   718      * @see #addIfAbsent(Object)
   719      */
   720     public int addAllAbsent(Collection<? extends E> c) {
   721         Object[] cs = c.toArray();
   722         if (cs.length == 0)
   723             return 0;
   724         Object[] uniq = new Object[cs.length];
   725         final ReentrantLock lock = this.lock;
   726         lock.lock();
   727         try {
   728             Object[] elements = getArray();
   729             int len = elements.length;
   730             int added = 0;
   731             for (int i = 0; i < cs.length; ++i) { // scan for duplicates
   732                 Object e = cs[i];
   733                 if (indexOf(e, elements, 0, len) < 0 &&
   734                     indexOf(e, uniq, 0, added) < 0)
   735                     uniq[added++] = e;
   736             }
   737             if (added > 0) {
   738                 Object[] newElements = Arrays.copyOf(elements, len + added);
   739                 System.arraycopy(uniq, 0, newElements, len, added);
   740                 setArray(newElements);
   741             }
   742             return added;
   743         } finally {
   744             lock.unlock();
   745         }
   746     }
   747 
   748     /**
   749      * Removes all of the elements from this list.
   750      * The list will be empty after this call returns.
   751      */
   752     public void clear() {
   753         final ReentrantLock lock = this.lock;
   754         lock.lock();
   755         try {
   756             setArray(new Object[0]);
   757         } finally {
   758             lock.unlock();
   759         }
   760     }
   761 
   762     /**
   763      * Appends all of the elements in the specified collection to the end
   764      * of this list, in the order that they are returned by the specified
   765      * collection's iterator.
   766      *
   767      * @param c collection containing elements to be added to this list
   768      * @return <tt>true</tt> if this list changed as a result of the call
   769      * @throws NullPointerException if the specified collection is null
   770      * @see #add(Object)
   771      */
   772     public boolean addAll(Collection<? extends E> c) {
   773         Object[] cs = c.toArray();
   774         if (cs.length == 0)
   775             return false;
   776         final ReentrantLock lock = this.lock;
   777         lock.lock();
   778         try {
   779             Object[] elements = getArray();
   780             int len = elements.length;
   781             Object[] newElements = Arrays.copyOf(elements, len + cs.length);
   782             System.arraycopy(cs, 0, newElements, len, cs.length);
   783             setArray(newElements);
   784             return true;
   785         } finally {
   786             lock.unlock();
   787         }
   788     }
   789 
   790     /**
   791      * Inserts all of the elements in the specified collection into this
   792      * list, starting at the specified position.  Shifts the element
   793      * currently at that position (if any) and any subsequent elements to
   794      * the right (increases their indices).  The new elements will appear
   795      * in this list in the order that they are returned by the
   796      * specified collection's iterator.
   797      *
   798      * @param index index at which to insert the first element
   799      *        from the specified collection
   800      * @param c collection containing elements to be added to this list
   801      * @return <tt>true</tt> if this list changed as a result of the call
   802      * @throws IndexOutOfBoundsException {@inheritDoc}
   803      * @throws NullPointerException if the specified collection is null
   804      * @see #add(int,Object)
   805      */
   806     public boolean addAll(int index, Collection<? extends E> c) {
   807         Object[] cs = c.toArray();
   808         final ReentrantLock lock = this.lock;
   809         lock.lock();
   810         try {
   811             Object[] elements = getArray();
   812             int len = elements.length;
   813             if (index > len || index < 0)
   814                 throw new IndexOutOfBoundsException("Index: "+index+
   815                                                     ", Size: "+len);
   816             if (cs.length == 0)
   817                 return false;
   818             int numMoved = len - index;
   819             Object[] newElements;
   820             if (numMoved == 0)
   821                 newElements = Arrays.copyOf(elements, len + cs.length);
   822             else {
   823                 newElements = new Object[len + cs.length];
   824                 System.arraycopy(elements, 0, newElements, 0, index);
   825                 System.arraycopy(elements, index,
   826                                  newElements, index + cs.length,
   827                                  numMoved);
   828             }
   829             System.arraycopy(cs, 0, newElements, index, cs.length);
   830             setArray(newElements);
   831             return true;
   832         } finally {
   833             lock.unlock();
   834         }
   835     }
   836 
   837     /**
   838      * Saves the state of the list to a stream (that is, serializes it).
   839      *
   840      * @serialData The length of the array backing the list is emitted
   841      *               (int), followed by all of its elements (each an Object)
   842      *               in the proper order.
   843      * @param s the stream
   844      */
   845     private void writeObject(java.io.ObjectOutputStream s)
   846         throws java.io.IOException{
   847 
   848         s.defaultWriteObject();
   849 
   850         Object[] elements = getArray();
   851         // Write out array length
   852         s.writeInt(elements.length);
   853 
   854         // Write out all elements in the proper order.
   855         for (Object element : elements)
   856             s.writeObject(element);
   857     }
   858 
   859     /**
   860      * Reconstitutes the list from a stream (that is, deserializes it).
   861      *
   862      * @param s the stream
   863      */
   864     private void readObject(java.io.ObjectInputStream s)
   865         throws java.io.IOException, ClassNotFoundException {
   866 
   867         s.defaultReadObject();
   868 
   869         // bind to new lock
   870         resetLock();
   871 
   872         // Read in array length and allocate array
   873         int len = s.readInt();
   874         Object[] elements = new Object[len];
   875 
   876         // Read in all elements in the proper order.
   877         for (int i = 0; i < len; i++)
   878             elements[i] = s.readObject();
   879         setArray(elements);
   880     }
   881 
   882     /**
   883      * Returns a string representation of this list.  The string
   884      * representation consists of the string representations of the list's
   885      * elements in the order they are returned by its iterator, enclosed in
   886      * square brackets (<tt>"[]"</tt>).  Adjacent elements are separated by
   887      * the characters <tt>", "</tt> (comma and space).  Elements are
   888      * converted to strings as by {@link String#valueOf(Object)}.
   889      *
   890      * @return a string representation of this list
   891      */
   892     public String toString() {
   893         return Arrays.toString(getArray());
   894     }
   895 
   896     /**
   897      * Compares the specified object with this list for equality.
   898      * Returns {@code true} if the specified object is the same object
   899      * as this object, or if it is also a {@link List} and the sequence
   900      * of elements returned by an {@linkplain List#iterator() iterator}
   901      * over the specified list is the same as the sequence returned by
   902      * an iterator over this list.  The two sequences are considered to
   903      * be the same if they have the same length and corresponding
   904      * elements at the same position in the sequence are <em>equal</em>.
   905      * Two elements {@code e1} and {@code e2} are considered
   906      * <em>equal</em> if {@code (e1==null ? e2==null : e1.equals(e2))}.
   907      *
   908      * @param o the object to be compared for equality with this list
   909      * @return {@code true} if the specified object is equal to this list
   910      */
   911     public boolean equals(Object o) {
   912         if (o == this)
   913             return true;
   914         if (!(o instanceof List))
   915             return false;
   916 
   917         List<?> list = (List<?>)(o);
   918         Iterator<?> it = list.iterator();
   919         Object[] elements = getArray();
   920         int len = elements.length;
   921         for (int i = 0; i < len; ++i)
   922             if (!it.hasNext() || !eq(elements[i], it.next()))
   923                 return false;
   924         if (it.hasNext())
   925             return false;
   926         return true;
   927     }
   928 
   929     /**
   930      * Returns the hash code value for this list.
   931      *
   932      * <p>This implementation uses the definition in {@link List#hashCode}.
   933      *
   934      * @return the hash code value for this list
   935      */
   936     public int hashCode() {
   937         int hashCode = 1;
   938         Object[] elements = getArray();
   939         int len = elements.length;
   940         for (int i = 0; i < len; ++i) {
   941             Object obj = elements[i];
   942             hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
   943         }
   944         return hashCode;
   945     }
   946 
   947     /**
   948      * Returns an iterator over the elements in this list in proper sequence.
   949      *
   950      * <p>The returned iterator provides a snapshot of the state of the list
   951      * when the iterator was constructed. No synchronization is needed while
   952      * traversing the iterator. The iterator does <em>NOT</em> support the
   953      * <tt>remove</tt> method.
   954      *
   955      * @return an iterator over the elements in this list in proper sequence
   956      */
   957     public Iterator<E> iterator() {
   958         return new COWIterator<E>(getArray(), 0);
   959     }
   960 
   961     /**
   962      * {@inheritDoc}
   963      *
   964      * <p>The returned iterator provides a snapshot of the state of the list
   965      * when the iterator was constructed. No synchronization is needed while
   966      * traversing the iterator. The iterator does <em>NOT</em> support the
   967      * <tt>remove</tt>, <tt>set</tt> or <tt>add</tt> methods.
   968      */
   969     public ListIterator<E> listIterator() {
   970         return new COWIterator<E>(getArray(), 0);
   971     }
   972 
   973     /**
   974      * {@inheritDoc}
   975      *
   976      * <p>The returned iterator provides a snapshot of the state of the list
   977      * when the iterator was constructed. No synchronization is needed while
   978      * traversing the iterator. The iterator does <em>NOT</em> support the
   979      * <tt>remove</tt>, <tt>set</tt> or <tt>add</tt> methods.
   980      *
   981      * @throws IndexOutOfBoundsException {@inheritDoc}
   982      */
   983     public ListIterator<E> listIterator(final int index) {
   984         Object[] elements = getArray();
   985         int len = elements.length;
   986         if (index<0 || index>len)
   987             throw new IndexOutOfBoundsException("Index: "+index);
   988 
   989         return new COWIterator<E>(elements, index);
   990     }
   991 
   992     private static class COWIterator<E> implements ListIterator<E> {
   993         /** Snapshot of the array */
   994         private final Object[] snapshot;
   995         /** Index of element to be returned by subsequent call to next.  */
   996         private int cursor;
   997 
   998         private COWIterator(Object[] elements, int initialCursor) {
   999             cursor = initialCursor;
  1000             snapshot = elements;
  1001         }
  1002 
  1003         public boolean hasNext() {
  1004             return cursor < snapshot.length;
  1005         }
  1006 
  1007         public boolean hasPrevious() {
  1008             return cursor > 0;
  1009         }
  1010 
  1011         @SuppressWarnings("unchecked")
  1012         public E next() {
  1013             if (! hasNext())
  1014                 throw new NoSuchElementException();
  1015             return (E) snapshot[cursor++];
  1016         }
  1017 
  1018         @SuppressWarnings("unchecked")
  1019         public E previous() {
  1020             if (! hasPrevious())
  1021                 throw new NoSuchElementException();
  1022             return (E) snapshot[--cursor];
  1023         }
  1024 
  1025         public int nextIndex() {
  1026             return cursor;
  1027         }
  1028 
  1029         public int previousIndex() {
  1030             return cursor-1;
  1031         }
  1032 
  1033         /**
  1034          * Not supported. Always throws UnsupportedOperationException.
  1035          * @throws UnsupportedOperationException always; <tt>remove</tt>
  1036          *         is not supported by this iterator.
  1037          */
  1038         public void remove() {
  1039             throw new UnsupportedOperationException();
  1040         }
  1041 
  1042         /**
  1043          * Not supported. Always throws UnsupportedOperationException.
  1044          * @throws UnsupportedOperationException always; <tt>set</tt>
  1045          *         is not supported by this iterator.
  1046          */
  1047         public void set(E e) {
  1048             throw new UnsupportedOperationException();
  1049         }
  1050 
  1051         /**
  1052          * Not supported. Always throws UnsupportedOperationException.
  1053          * @throws UnsupportedOperationException always; <tt>add</tt>
  1054          *         is not supported by this iterator.
  1055          */
  1056         public void add(E e) {
  1057             throw new UnsupportedOperationException();
  1058         }
  1059     }
  1060 
  1061     /**
  1062      * Returns a view of the portion of this list between
  1063      * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
  1064      * The returned list is backed by this list, so changes in the
  1065      * returned list are reflected in this list.
  1066      *
  1067      * <p>The semantics of the list returned by this method become
  1068      * undefined if the backing list (i.e., this list) is modified in
  1069      * any way other than via the returned list.
  1070      *
  1071      * @param fromIndex low endpoint (inclusive) of the subList
  1072      * @param toIndex high endpoint (exclusive) of the subList
  1073      * @return a view of the specified range within this list
  1074      * @throws IndexOutOfBoundsException {@inheritDoc}
  1075      */
  1076     public List<E> subList(int fromIndex, int toIndex) {
  1077         final ReentrantLock lock = this.lock;
  1078         lock.lock();
  1079         try {
  1080             Object[] elements = getArray();
  1081             int len = elements.length;
  1082             if (fromIndex < 0 || toIndex > len || fromIndex > toIndex)
  1083                 throw new IndexOutOfBoundsException();
  1084             return new COWSubList<E>(this, fromIndex, toIndex);
  1085         } finally {
  1086             lock.unlock();
  1087         }
  1088     }
  1089 
  1090     /**
  1091      * Sublist for CopyOnWriteArrayList.
  1092      * This class extends AbstractList merely for convenience, to
  1093      * avoid having to define addAll, etc. This doesn't hurt, but
  1094      * is wasteful.  This class does not need or use modCount
  1095      * mechanics in AbstractList, but does need to check for
  1096      * concurrent modification using similar mechanics.  On each
  1097      * operation, the array that we expect the backing list to use
  1098      * is checked and updated.  Since we do this for all of the
  1099      * base operations invoked by those defined in AbstractList,
  1100      * all is well.  While inefficient, this is not worth
  1101      * improving.  The kinds of list operations inherited from
  1102      * AbstractList are already so slow on COW sublists that
  1103      * adding a bit more space/time doesn't seem even noticeable.
  1104      */
  1105     private static class COWSubList<E>
  1106         extends AbstractList<E>
  1107         implements RandomAccess
  1108     {
  1109         private final CopyOnWriteArrayList<E> l;
  1110         private final int offset;
  1111         private int size;
  1112         private Object[] expectedArray;
  1113 
  1114         // only call this holding l's lock
  1115         COWSubList(CopyOnWriteArrayList<E> list,
  1116                    int fromIndex, int toIndex) {
  1117             l = list;
  1118             expectedArray = l.getArray();
  1119             offset = fromIndex;
  1120             size = toIndex - fromIndex;
  1121         }
  1122 
  1123         // only call this holding l's lock
  1124         private void checkForComodification() {
  1125             if (l.getArray() != expectedArray)
  1126                 throw new ConcurrentModificationException();
  1127         }
  1128 
  1129         // only call this holding l's lock
  1130         private void rangeCheck(int index) {
  1131             if (index<0 || index>=size)
  1132                 throw new IndexOutOfBoundsException("Index: "+index+
  1133                                                     ",Size: "+size);
  1134         }
  1135 
  1136         public E set(int index, E element) {
  1137             final ReentrantLock lock = l.lock;
  1138             lock.lock();
  1139             try {
  1140                 rangeCheck(index);
  1141                 checkForComodification();
  1142                 E x = l.set(index+offset, element);
  1143                 expectedArray = l.getArray();
  1144                 return x;
  1145             } finally {
  1146                 lock.unlock();
  1147             }
  1148         }
  1149 
  1150         public E get(int index) {
  1151             final ReentrantLock lock = l.lock;
  1152             lock.lock();
  1153             try {
  1154                 rangeCheck(index);
  1155                 checkForComodification();
  1156                 return l.get(index+offset);
  1157             } finally {
  1158                 lock.unlock();
  1159             }
  1160         }
  1161 
  1162         public int size() {
  1163             final ReentrantLock lock = l.lock;
  1164             lock.lock();
  1165             try {
  1166                 checkForComodification();
  1167                 return size;
  1168             } finally {
  1169                 lock.unlock();
  1170             }
  1171         }
  1172 
  1173         public void add(int index, E element) {
  1174             final ReentrantLock lock = l.lock;
  1175             lock.lock();
  1176             try {
  1177                 checkForComodification();
  1178                 if (index<0 || index>size)
  1179                     throw new IndexOutOfBoundsException();
  1180                 l.add(index+offset, element);
  1181                 expectedArray = l.getArray();
  1182                 size++;
  1183             } finally {
  1184                 lock.unlock();
  1185             }
  1186         }
  1187 
  1188         public void clear() {
  1189             final ReentrantLock lock = l.lock;
  1190             lock.lock();
  1191             try {
  1192                 checkForComodification();
  1193                 l.removeRange(offset, offset+size);
  1194                 expectedArray = l.getArray();
  1195                 size = 0;
  1196             } finally {
  1197                 lock.unlock();
  1198             }
  1199         }
  1200 
  1201         public E remove(int index) {
  1202             final ReentrantLock lock = l.lock;
  1203             lock.lock();
  1204             try {
  1205                 rangeCheck(index);
  1206                 checkForComodification();
  1207                 E result = l.remove(index+offset);
  1208                 expectedArray = l.getArray();
  1209                 size--;
  1210                 return result;
  1211             } finally {
  1212                 lock.unlock();
  1213             }
  1214         }
  1215 
  1216         public boolean remove(Object o) {
  1217             int index = indexOf(o);
  1218             if (index == -1)
  1219                 return false;
  1220             remove(index);
  1221             return true;
  1222         }
  1223 
  1224         public Iterator<E> iterator() {
  1225             final ReentrantLock lock = l.lock;
  1226             lock.lock();
  1227             try {
  1228                 checkForComodification();
  1229                 return new COWSubListIterator<E>(l, 0, offset, size);
  1230             } finally {
  1231                 lock.unlock();
  1232             }
  1233         }
  1234 
  1235         public ListIterator<E> listIterator(final int index) {
  1236             final ReentrantLock lock = l.lock;
  1237             lock.lock();
  1238             try {
  1239                 checkForComodification();
  1240                 if (index<0 || index>size)
  1241                     throw new IndexOutOfBoundsException("Index: "+index+
  1242                                                         ", Size: "+size);
  1243                 return new COWSubListIterator<E>(l, index, offset, size);
  1244             } finally {
  1245                 lock.unlock();
  1246             }
  1247         }
  1248 
  1249         public List<E> subList(int fromIndex, int toIndex) {
  1250             final ReentrantLock lock = l.lock;
  1251             lock.lock();
  1252             try {
  1253                 checkForComodification();
  1254                 if (fromIndex<0 || toIndex>size)
  1255                     throw new IndexOutOfBoundsException();
  1256                 return new COWSubList<E>(l, fromIndex + offset,
  1257                                          toIndex + offset);
  1258             } finally {
  1259                 lock.unlock();
  1260             }
  1261         }
  1262 
  1263     }
  1264 
  1265 
  1266     private static class COWSubListIterator<E> implements ListIterator<E> {
  1267         private final ListIterator<E> i;
  1268         private final int index;
  1269         private final int offset;
  1270         private final int size;
  1271 
  1272         COWSubListIterator(List<E> l, int index, int offset,
  1273                            int size) {
  1274             this.index = index;
  1275             this.offset = offset;
  1276             this.size = size;
  1277             i = l.listIterator(index+offset);
  1278         }
  1279 
  1280         public boolean hasNext() {
  1281             return nextIndex() < size;
  1282         }
  1283 
  1284         public E next() {
  1285             if (hasNext())
  1286                 return i.next();
  1287             else
  1288                 throw new NoSuchElementException();
  1289         }
  1290 
  1291         public boolean hasPrevious() {
  1292             return previousIndex() >= 0;
  1293         }
  1294 
  1295         public E previous() {
  1296             if (hasPrevious())
  1297                 return i.previous();
  1298             else
  1299                 throw new NoSuchElementException();
  1300         }
  1301 
  1302         public int nextIndex() {
  1303             return i.nextIndex() - offset;
  1304         }
  1305 
  1306         public int previousIndex() {
  1307             return i.previousIndex() - offset;
  1308         }
  1309 
  1310         public void remove() {
  1311             throw new UnsupportedOperationException();
  1312         }
  1313 
  1314         public void set(E e) {
  1315             throw new UnsupportedOperationException();
  1316         }
  1317 
  1318         public void add(E e) {
  1319             throw new UnsupportedOperationException();
  1320         }
  1321     }
  1322 
  1323     // Support for resetting lock while deserializing
  1324     private void resetLock() {
  1325         this.lock = new ReentrantLock();
  1326     }
  1327 }