ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk7/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.3
Committed: Fri Jan 18 04:23:27 2013 UTC (11 years, 4 months ago) by jsr166
Branch: MAIN
Changes since 1.2: +2 -2 lines
Log Message:
use blessed modifier order

File Contents

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