ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.81
Committed: Thu Jun 9 07:48:43 2011 UTC (12 years, 11 months ago) by jsr166
Branch: MAIN
Changes since 1.80: +1 -2 lines
Log Message:
consistent style for code snippets

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