ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jdk7/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.9
Committed: Sun Feb 22 05:08:16 2015 UTC (9 years, 3 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.8: +1 -1 lines
Log Message:
COWIterator constructor should not be private

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