ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.104
Committed: Fri Apr 12 20:23:03 2013 UTC (11 years, 2 months ago) by jsr166
Branch: MAIN
Changes since 1.103: +54 -30 lines
Log Message:
optimize addIfAbsent and remove(Object) for non-mutating case

File Contents

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