ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.77
Committed: Wed Jun 8 00:50:35 2011 UTC (13 years ago) by jsr166
Branch: MAIN
Changes since 1.76: +0 -1 lines
Log Message:
clean up imports

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     * <pre>
316     * String[] y = x.toArray(new String[0]);</pre>
317     *
318     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
319     * <tt>toArray()</tt>.
320 tim 1.1 *
321     * @param a the array into which the elements of the list are to
322 jsr166 1.35 * be stored, if it is big enough; otherwise, a new array of the
323     * same runtime type is allocated for this purpose.
324     * @return an array containing all the elements in this list
325     * @throws ArrayStoreException if the runtime type of the specified array
326     * is not a supertype of the runtime type of every element in
327     * this list
328     * @throws NullPointerException if the specified array is null
329 tim 1.1 */
330 jsr166 1.66 @SuppressWarnings("unchecked")
331 tim 1.1 public <T> T[] toArray(T a[]) {
332 dl 1.41 Object[] elements = getArray();
333 dl 1.40 int len = elements.length;
334     if (a.length < len)
335 jsr166 1.67 return (T[]) Arrays.copyOf(elements, len, a.getClass());
336     else {
337     System.arraycopy(elements, 0, a, 0, len);
338     if (a.length > len)
339     a[len] = null;
340     return a;
341     }
342 tim 1.1 }
343    
344     // Positional Access Operations
345    
346 jsr166 1.66 @SuppressWarnings("unchecked")
347     private E get(Object[] a, int index) {
348 jsr166 1.67 return (E) a[index];
349 jsr166 1.66 }
350    
351 tim 1.1 /**
352 jsr166 1.35 * {@inheritDoc}
353 tim 1.1 *
354 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
355 tim 1.1 */
356     public E get(int index) {
357 jsr166 1.66 return get(getArray(), index);
358 tim 1.1 }
359    
360     /**
361 jsr166 1.35 * Replaces the element at the specified position in this list with the
362     * specified element.
363 tim 1.1 *
364 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
365 tim 1.1 */
366 dl 1.42 public E set(int index, E element) {
367 jsr166 1.67 final ReentrantLock lock = this.lock;
368     lock.lock();
369     try {
370     Object[] elements = getArray();
371     E oldValue = get(elements, index);
372    
373     if (oldValue != element) {
374     int len = elements.length;
375     Object[] newElements = Arrays.copyOf(elements, len);
376     newElements[index] = element;
377     setArray(newElements);
378     } else {
379     // Not quite a no-op; ensures volatile write semantics
380     setArray(elements);
381     }
382     return oldValue;
383     } finally {
384     lock.unlock();
385     }
386 tim 1.1 }
387    
388     /**
389     * Appends the specified element to the end of this list.
390     *
391 dl 1.40 * @param e element to be appended to this list
392 jsr166 1.49 * @return <tt>true</tt> (as specified by {@link Collection#add})
393 tim 1.1 */
394 dl 1.42 public boolean add(E e) {
395 jsr166 1.67 final ReentrantLock lock = this.lock;
396     lock.lock();
397     try {
398     Object[] elements = getArray();
399     int len = elements.length;
400     Object[] newElements = Arrays.copyOf(elements, len + 1);
401     newElements[len] = e;
402     setArray(newElements);
403     return true;
404     } finally {
405     lock.unlock();
406     }
407 tim 1.1 }
408    
409     /**
410     * Inserts the specified element at the specified position in this
411     * list. Shifts the element currently at that position (if any) and
412     * any subsequent elements to the right (adds one to their indices).
413     *
414 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
415 tim 1.1 */
416 dl 1.42 public void add(int index, E element) {
417 jsr166 1.67 final ReentrantLock lock = this.lock;
418     lock.lock();
419     try {
420     Object[] elements = getArray();
421     int len = elements.length;
422     if (index > len || index < 0)
423     throw new IndexOutOfBoundsException("Index: "+index+
424     ", Size: "+len);
425     Object[] newElements;
426     int numMoved = len - index;
427     if (numMoved == 0)
428     newElements = Arrays.copyOf(elements, len + 1);
429     else {
430     newElements = new Object[len + 1];
431     System.arraycopy(elements, 0, newElements, 0, index);
432     System.arraycopy(elements, index, newElements, index + 1,
433     numMoved);
434     }
435     newElements[index] = element;
436     setArray(newElements);
437     } finally {
438     lock.unlock();
439     }
440 tim 1.1 }
441    
442     /**
443     * Removes the element at the specified position in this list.
444     * Shifts any subsequent elements to the left (subtracts one from their
445 jsr166 1.35 * indices). Returns the element that was removed from the list.
446 tim 1.1 *
447 jsr166 1.35 * @throws IndexOutOfBoundsException {@inheritDoc}
448 tim 1.1 */
449 dl 1.42 public E remove(int index) {
450 jsr166 1.67 final ReentrantLock lock = this.lock;
451     lock.lock();
452     try {
453     Object[] elements = getArray();
454     int len = elements.length;
455     E oldValue = get(elements, index);
456     int numMoved = len - index - 1;
457     if (numMoved == 0)
458     setArray(Arrays.copyOf(elements, len - 1));
459     else {
460     Object[] newElements = new Object[len - 1];
461     System.arraycopy(elements, 0, newElements, 0, index);
462     System.arraycopy(elements, index + 1, newElements, index,
463     numMoved);
464     setArray(newElements);
465     }
466     return oldValue;
467     } finally {
468     lock.unlock();
469     }
470 tim 1.1 }
471    
472     /**
473 jsr166 1.35 * Removes the first occurrence of the specified element from this list,
474     * if it is present. If this list does not contain the element, it is
475     * unchanged. More formally, removes the element with the lowest index
476     * <tt>i</tt> such that
477     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
478     * (if such an element exists). Returns <tt>true</tt> if this list
479     * contained the specified element (or equivalently, if this list
480     * changed as a result of the call).
481 tim 1.1 *
482 jsr166 1.35 * @param o element to be removed from this list, if present
483     * @return <tt>true</tt> if this list contained the specified element
484 tim 1.1 */
485 dl 1.42 public boolean remove(Object o) {
486 jsr166 1.67 final ReentrantLock lock = this.lock;
487     lock.lock();
488     try {
489     Object[] elements = getArray();
490     int len = elements.length;
491     if (len != 0) {
492     // Copy while searching for element to remove
493     // This wins in the normal case of element being present
494     int newlen = len - 1;
495     Object[] newElements = new Object[newlen];
496    
497     for (int i = 0; i < newlen; ++i) {
498     if (eq(o, elements[i])) {
499     // found one; copy remaining and exit
500     for (int k = i + 1; k < len; ++k)
501     newElements[k-1] = elements[k];
502     setArray(newElements);
503     return true;
504     } else
505     newElements[i] = elements[i];
506     }
507    
508     // special handling for last cell
509     if (eq(o, elements[newlen])) {
510     setArray(newElements);
511     return true;
512     }
513     }
514     return false;
515     } finally {
516     lock.unlock();
517     }
518 tim 1.1 }
519    
520     /**
521 jsr166 1.35 * Removes from this list all of the elements whose index is between
522     * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
523     * Shifts any succeeding elements to the left (reduces their index).
524 dl 1.15 * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements.
525     * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.)
526 tim 1.1 *
527 jsr166 1.35 * @param fromIndex index of first element to be removed
528     * @param toIndex index after last element to be removed
529 jsr166 1.66 * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range
530 jsr166 1.69 * ({@code{fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
531 tim 1.1 */
532 dl 1.42 private void removeRange(int fromIndex, int toIndex) {
533 jsr166 1.67 final ReentrantLock lock = this.lock;
534     lock.lock();
535     try {
536     Object[] elements = getArray();
537     int len = elements.length;
538    
539     if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)
540     throw new IndexOutOfBoundsException();
541     int newlen = len - (toIndex - fromIndex);
542     int numMoved = len - toIndex;
543     if (numMoved == 0)
544     setArray(Arrays.copyOf(elements, newlen));
545     else {
546     Object[] newElements = new Object[newlen];
547     System.arraycopy(elements, 0, newElements, 0, fromIndex);
548     System.arraycopy(elements, toIndex, newElements,
549     fromIndex, numMoved);
550     setArray(newElements);
551     }
552     } finally {
553     lock.unlock();
554     }
555 tim 1.1 }
556    
557     /**
558     * Append the element if not present.
559 jsr166 1.38 *
560 dl 1.40 * @param e element to be added to this list, if absent
561 jsr166 1.38 * @return <tt>true</tt> if the element was added
562 jsr166 1.30 */
563 dl 1.42 public boolean addIfAbsent(E e) {
564 jsr166 1.67 final ReentrantLock lock = this.lock;
565     lock.lock();
566     try {
567     // Copy while checking if already present.
568     // This wins in the most common case where it is not present
569     Object[] elements = getArray();
570     int len = elements.length;
571     Object[] newElements = new Object[len + 1];
572     for (int i = 0; i < len; ++i) {
573     if (eq(e, elements[i]))
574     return false; // exit, throwing away copy
575     else
576     newElements[i] = elements[i];
577     }
578     newElements[len] = e;
579     setArray(newElements);
580     return true;
581     } finally {
582     lock.unlock();
583     }
584 tim 1.1 }
585    
586     /**
587 jsr166 1.35 * Returns <tt>true</tt> if this list contains all of the elements of the
588 jsr166 1.32 * specified collection.
589 jsr166 1.34 *
590 jsr166 1.36 * @param c collection to be checked for containment in this list
591 jsr166 1.35 * @return <tt>true</tt> if this list contains all of the elements of the
592     * specified collection
593     * @throws NullPointerException if the specified collection is null
594 jsr166 1.38 * @see #contains(Object)
595 tim 1.1 */
596 tim 1.7 public boolean containsAll(Collection<?> c) {
597 dl 1.41 Object[] elements = getArray();
598 dl 1.40 int len = elements.length;
599 jsr166 1.67 for (Object e : c) {
600 dl 1.41 if (indexOf(e, elements, 0, len) < 0)
601 tim 1.1 return false;
602 jsr166 1.67 }
603 tim 1.1 return true;
604     }
605    
606     /**
607 jsr166 1.32 * Removes from this list all of its elements that are contained in
608     * the specified collection. This is a particularly expensive operation
609 tim 1.1 * in this class because of the need for an internal temporary array.
610     *
611 jsr166 1.35 * @param c collection containing elements to be removed from this list
612     * @return <tt>true</tt> if this list changed as a result of the call
613 jsr166 1.38 * @throws ClassCastException if the class of an element of this list
614 dl 1.73 * is incompatible with the specified collection
615 dl 1.74 * (<a href="../Collection.html#optional-restrictions">optional</a>)
616 jsr166 1.38 * @throws NullPointerException if this list contains a null element and the
617 dl 1.73 * specified collection does not permit null elements
618 dl 1.75 * (<a href="../Collection.html#optional-restrictions">optional</a>),
619 jsr166 1.38 * or if the specified collection is null
620     * @see #remove(Object)
621 tim 1.1 */
622 dl 1.42 public boolean removeAll(Collection<?> c) {
623 jsr166 1.67 final ReentrantLock lock = this.lock;
624     lock.lock();
625     try {
626     Object[] elements = getArray();
627     int len = elements.length;
628     if (len != 0) {
629     // temp array holds those elements we know we want to keep
630     int newlen = 0;
631     Object[] temp = new Object[len];
632     for (int i = 0; i < len; ++i) {
633     Object element = elements[i];
634     if (!c.contains(element))
635     temp[newlen++] = element;
636     }
637     if (newlen != len) {
638     setArray(Arrays.copyOf(temp, newlen));
639     return true;
640     }
641     }
642     return false;
643     } finally {
644     lock.unlock();
645     }
646 tim 1.1 }
647    
648     /**
649 jsr166 1.32 * Retains only the elements in this list that are contained in the
650 jsr166 1.35 * specified collection. In other words, removes from this list all of
651     * its elements that are not contained in the specified collection.
652 jsr166 1.32 *
653 jsr166 1.35 * @param c collection containing elements to be retained in this list
654     * @return <tt>true</tt> if this list changed as a result of the call
655 jsr166 1.38 * @throws ClassCastException if the class of an element of this list
656 dl 1.73 * is incompatible with the specified collection
657 dl 1.74 * (<a href="../Collection.html#optional-restrictions">optional</a>)
658 jsr166 1.38 * @throws NullPointerException if this list contains a null element and the
659 dl 1.73 * specified collection does not permit null elements
660 dl 1.75 * (<a href="../Collection.html#optional-restrictions">optional</a>),
661 jsr166 1.38 * or if the specified collection is null
662     * @see #remove(Object)
663 tim 1.1 */
664 dl 1.42 public boolean retainAll(Collection<?> c) {
665 jsr166 1.67 final ReentrantLock lock = this.lock;
666     lock.lock();
667     try {
668     Object[] elements = getArray();
669     int len = elements.length;
670     if (len != 0) {
671     // temp array holds those elements we know we want to keep
672     int newlen = 0;
673     Object[] temp = new Object[len];
674     for (int i = 0; i < len; ++i) {
675     Object element = elements[i];
676     if (c.contains(element))
677     temp[newlen++] = element;
678     }
679     if (newlen != len) {
680     setArray(Arrays.copyOf(temp, newlen));
681     return true;
682     }
683     }
684     return false;
685     } finally {
686     lock.unlock();
687     }
688 tim 1.1 }
689    
690     /**
691 jsr166 1.32 * Appends all of the elements in the specified collection that
692 tim 1.1 * are not already contained in this list, to the end of
693     * this list, in the order that they are returned by the
694 jsr166 1.32 * specified collection's iterator.
695 tim 1.1 *
696 jsr166 1.36 * @param c collection containing elements to be added to this list
697 tim 1.1 * @return the number of elements added
698 jsr166 1.35 * @throws NullPointerException if the specified collection is null
699 jsr166 1.38 * @see #addIfAbsent(Object)
700 tim 1.1 */
701 dl 1.42 public int addAllAbsent(Collection<? extends E> c) {
702 jsr166 1.67 Object[] cs = c.toArray();
703     if (cs.length == 0)
704     return 0;
705     Object[] uniq = new Object[cs.length];
706     final ReentrantLock lock = this.lock;
707     lock.lock();
708     try {
709     Object[] elements = getArray();
710     int len = elements.length;
711     int added = 0;
712     for (int i = 0; i < cs.length; ++i) { // scan for duplicates
713     Object e = cs[i];
714     if (indexOf(e, elements, 0, len) < 0 &&
715     indexOf(e, uniq, 0, added) < 0)
716     uniq[added++] = e;
717     }
718     if (added > 0) {
719     Object[] newElements = Arrays.copyOf(elements, len + added);
720     System.arraycopy(uniq, 0, newElements, len, added);
721     setArray(newElements);
722     }
723     return added;
724     } finally {
725     lock.unlock();
726     }
727 tim 1.1 }
728    
729     /**
730     * Removes all of the elements from this list.
731 jsr166 1.38 * The list will be empty after this call returns.
732 tim 1.1 */
733 dl 1.42 public void clear() {
734 jsr166 1.67 final ReentrantLock lock = this.lock;
735     lock.lock();
736     try {
737     setArray(new Object[0]);
738     } finally {
739     lock.unlock();
740     }
741 tim 1.1 }
742    
743     /**
744 jsr166 1.32 * Appends all of the elements in the specified collection to the end
745     * of this list, in the order that they are returned by the specified
746     * collection's iterator.
747 tim 1.1 *
748 jsr166 1.36 * @param c collection containing elements to be added to this list
749 jsr166 1.38 * @return <tt>true</tt> if this list changed as a result of the call
750 jsr166 1.35 * @throws NullPointerException if the specified collection is null
751 jsr166 1.38 * @see #add(Object)
752 tim 1.1 */
753 dl 1.42 public boolean addAll(Collection<? extends E> c) {
754 jsr166 1.67 Object[] cs = c.toArray();
755     if (cs.length == 0)
756     return false;
757     final ReentrantLock lock = this.lock;
758     lock.lock();
759     try {
760     Object[] elements = getArray();
761     int len = elements.length;
762     Object[] newElements = Arrays.copyOf(elements, len + cs.length);
763     System.arraycopy(cs, 0, newElements, len, cs.length);
764     setArray(newElements);
765     return true;
766     } finally {
767     lock.unlock();
768     }
769 tim 1.1 }
770    
771     /**
772 jsr166 1.35 * Inserts all of the elements in the specified collection into this
773 tim 1.1 * list, starting at the specified position. Shifts the element
774     * currently at that position (if any) and any subsequent elements to
775     * the right (increases their indices). The new elements will appear
776 jsr166 1.38 * in this list in the order that they are returned by the
777     * specified collection's iterator.
778 tim 1.1 *
779 jsr166 1.35 * @param index index at which to insert the first element
780     * from the specified collection
781 jsr166 1.36 * @param c collection containing elements to be added to this list
782 jsr166 1.35 * @return <tt>true</tt> if this list changed as a result of the call
783     * @throws IndexOutOfBoundsException {@inheritDoc}
784     * @throws NullPointerException if the specified collection is null
785 jsr166 1.38 * @see #add(int,Object)
786 tim 1.1 */
787 dl 1.42 public boolean addAll(int index, Collection<? extends E> c) {
788 jsr166 1.67 Object[] cs = c.toArray();
789     final ReentrantLock lock = this.lock;
790     lock.lock();
791     try {
792     Object[] elements = getArray();
793     int len = elements.length;
794     if (index > len || index < 0)
795     throw new IndexOutOfBoundsException("Index: "+index+
796     ", Size: "+len);
797     if (cs.length == 0)
798     return false;
799     int numMoved = len - index;
800     Object[] newElements;
801     if (numMoved == 0)
802     newElements = Arrays.copyOf(elements, len + cs.length);
803     else {
804     newElements = new Object[len + cs.length];
805     System.arraycopy(elements, 0, newElements, 0, index);
806     System.arraycopy(elements, index,
807     newElements, index + cs.length,
808     numMoved);
809     }
810     System.arraycopy(cs, 0, newElements, index, cs.length);
811     setArray(newElements);
812     return true;
813     } finally {
814     lock.unlock();
815     }
816 tim 1.1 }
817    
818     /**
819 jsr166 1.70 * Saves the state of the list to a stream (that is, serializes it).
820 tim 1.1 *
821     * @serialData The length of the array backing the list is emitted
822     * (int), followed by all of its elements (each an Object)
823     * in the proper order.
824 dl 1.6 * @param s the stream
825 tim 1.1 */
826     private void writeObject(java.io.ObjectOutputStream s)
827     throws java.io.IOException{
828    
829     s.defaultWriteObject();
830    
831 dl 1.41 Object[] elements = getArray();
832 tim 1.1 // Write out array length
833 jsr166 1.71 s.writeInt(elements.length);
834 tim 1.1
835     // Write out all elements in the proper order.
836 jsr166 1.71 for (Object element : elements)
837     s.writeObject(element);
838 tim 1.1 }
839    
840     /**
841 jsr166 1.70 * Reconstitutes the list from a stream (that is, deserializes it).
842     *
843 dl 1.6 * @param s the stream
844 tim 1.1 */
845 dl 1.12 private void readObject(java.io.ObjectInputStream s)
846 tim 1.1 throws java.io.IOException, ClassNotFoundException {
847    
848     s.defaultReadObject();
849    
850 dl 1.42 // bind to new lock
851     resetLock();
852    
853 tim 1.1 // Read in array length and allocate array
854 dl 1.40 int len = s.readInt();
855 dl 1.41 Object[] elements = new Object[len];
856 tim 1.1
857     // Read in all elements in the proper order.
858 dl 1.40 for (int i = 0; i < len; i++)
859 dl 1.41 elements[i] = s.readObject();
860 dl 1.40 setArray(elements);
861 tim 1.1 }
862    
863     /**
864 jsr166 1.55 * Returns a string representation of this list. The string
865     * representation consists of the string representations of the list's
866     * elements in the order they are returned by its iterator, enclosed in
867     * square brackets (<tt>"[]"</tt>). Adjacent elements are separated by
868     * the characters <tt>", "</tt> (comma and space). Elements are
869     * converted to strings as by {@link String#valueOf(Object)}.
870     *
871     * @return a string representation of this list
872 tim 1.1 */
873     public String toString() {
874 jsr166 1.67 return Arrays.toString(getArray());
875 tim 1.1 }
876    
877     /**
878 jsr166 1.35 * Compares the specified object with this list for equality.
879 jsr166 1.60 * Returns {@code true} if the specified object is the same object
880     * as this object, or if it is also a {@link List} and the sequence
881     * of elements returned by an {@linkplain List#iterator() iterator}
882     * over the specified list is the same as the sequence returned by
883     * an iterator over this list. The two sequences are considered to
884     * be the same if they have the same length and corresponding
885     * elements at the same position in the sequence are <em>equal</em>.
886     * Two elements {@code e1} and {@code e2} are considered
887     * <em>equal</em> if {@code (e1==null ? e2==null : e1.equals(e2))}.
888 tim 1.1 *
889 jsr166 1.35 * @param o the object to be compared for equality with this list
890 jsr166 1.60 * @return {@code true} if the specified object is equal to this list
891 tim 1.1 */
892     public boolean equals(Object o) {
893     if (o == this)
894     return true;
895     if (!(o instanceof List))
896     return false;
897    
898 dl 1.57 List<?> list = (List<?>)(o);
899 jsr166 1.67 Iterator<?> it = list.iterator();
900     Object[] elements = getArray();
901     int len = elements.length;
902 jsr166 1.60 for (int i = 0; i < len; ++i)
903     if (!it.hasNext() || !eq(elements[i], it.next()))
904 dl 1.57 return false;
905 jsr166 1.60 if (it.hasNext())
906 tim 1.1 return false;
907     return true;
908     }
909    
910     /**
911 jsr166 1.35 * Returns the hash code value for this list.
912 dl 1.26 *
913 jsr166 1.47 * <p>This implementation uses the definition in {@link List#hashCode}.
914     *
915     * @return the hash code value for this list
916 tim 1.1 */
917     public int hashCode() {
918     int hashCode = 1;
919 jsr166 1.67 Object[] elements = getArray();
920     int len = elements.length;
921     for (int i = 0; i < len; ++i) {
922     Object obj = elements[i];
923 jsr166 1.45 hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
924 tim 1.1 }
925     return hashCode;
926     }
927    
928     /**
929 jsr166 1.35 * Returns an iterator over the elements in this list in proper sequence.
930     *
931     * <p>The returned iterator provides a snapshot of the state of the list
932     * when the iterator was constructed. No synchronization is needed while
933     * traversing the iterator. The iterator does <em>NOT</em> support the
934     * <tt>remove</tt> method.
935     *
936     * @return an iterator over the elements in this list in proper sequence
937 tim 1.1 */
938     public Iterator<E> iterator() {
939 dl 1.40 return new COWIterator<E>(getArray(), 0);
940 tim 1.1 }
941    
942     /**
943 jsr166 1.35 * {@inheritDoc}
944 tim 1.1 *
945 jsr166 1.35 * <p>The returned iterator provides a snapshot of the state of the list
946     * when the iterator was constructed. No synchronization is needed while
947     * traversing the iterator. The iterator does <em>NOT</em> support the
948     * <tt>remove</tt>, <tt>set</tt> or <tt>add</tt> methods.
949 tim 1.1 */
950     public ListIterator<E> listIterator() {
951 dl 1.40 return new COWIterator<E>(getArray(), 0);
952 tim 1.1 }
953    
954     /**
955 jsr166 1.35 * {@inheritDoc}
956     *
957 jsr166 1.50 * <p>The returned iterator provides a snapshot of the state of the list
958     * when the iterator was constructed. No synchronization is needed while
959     * traversing the iterator. The iterator does <em>NOT</em> support the
960     * <tt>remove</tt>, <tt>set</tt> or <tt>add</tt> methods.
961 jsr166 1.35 *
962     * @throws IndexOutOfBoundsException {@inheritDoc}
963 tim 1.1 */
964     public ListIterator<E> listIterator(final int index) {
965 dl 1.41 Object[] elements = getArray();
966 dl 1.40 int len = elements.length;
967 jsr166 1.45 if (index<0 || index>len)
968     throw new IndexOutOfBoundsException("Index: "+index);
969 tim 1.1
970 dl 1.48 return new COWIterator<E>(elements, index);
971 tim 1.1 }
972    
973     private static class COWIterator<E> implements ListIterator<E> {
974 jsr166 1.68 /** Snapshot of the array */
975 dl 1.41 private final Object[] snapshot;
976 dl 1.40 /** Index of element to be returned by subsequent call to next. */
977 tim 1.1 private int cursor;
978    
979 dl 1.41 private COWIterator(Object[] elements, int initialCursor) {
980 tim 1.1 cursor = initialCursor;
981 dl 1.40 snapshot = elements;
982 tim 1.1 }
983    
984     public boolean hasNext() {
985 dl 1.40 return cursor < snapshot.length;
986 tim 1.1 }
987    
988     public boolean hasPrevious() {
989     return cursor > 0;
990     }
991    
992 jsr166 1.67 @SuppressWarnings("unchecked")
993 tim 1.1 public E next() {
994 jsr166 1.67 if (! hasNext())
995 tim 1.1 throw new NoSuchElementException();
996 jsr166 1.67 return (E) snapshot[cursor++];
997 tim 1.1 }
998    
999 jsr166 1.67 @SuppressWarnings("unchecked")
1000 tim 1.1 public E previous() {
1001 jsr166 1.67 if (! hasPrevious())
1002 tim 1.1 throw new NoSuchElementException();
1003 jsr166 1.67 return (E) snapshot[--cursor];
1004 tim 1.1 }
1005    
1006     public int nextIndex() {
1007     return cursor;
1008     }
1009    
1010     public int previousIndex() {
1011 jsr166 1.45 return cursor-1;
1012 tim 1.1 }
1013    
1014     /**
1015     * Not supported. Always throws UnsupportedOperationException.
1016 jsr166 1.32 * @throws UnsupportedOperationException always; <tt>remove</tt>
1017     * is not supported by this iterator.
1018 tim 1.1 */
1019     public void remove() {
1020     throw new UnsupportedOperationException();
1021     }
1022    
1023     /**
1024     * Not supported. Always throws UnsupportedOperationException.
1025 jsr166 1.32 * @throws UnsupportedOperationException always; <tt>set</tt>
1026     * is not supported by this iterator.
1027 tim 1.1 */
1028 jsr166 1.33 public void set(E e) {
1029 tim 1.1 throw new UnsupportedOperationException();
1030     }
1031    
1032     /**
1033     * Not supported. Always throws UnsupportedOperationException.
1034 jsr166 1.32 * @throws UnsupportedOperationException always; <tt>add</tt>
1035     * is not supported by this iterator.
1036 tim 1.1 */
1037 jsr166 1.33 public void add(E e) {
1038 tim 1.1 throw new UnsupportedOperationException();
1039     }
1040     }
1041    
1042     /**
1043 dl 1.40 * Returns a view of the portion of this list between
1044     * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
1045     * The returned list is backed by this list, so changes in the
1046 jsr166 1.66 * returned list are reflected in this list.
1047 dl 1.40 *
1048     * <p>The semantics of the list returned by this method become
1049 jsr166 1.66 * undefined if the backing list (i.e., this list) is modified in
1050     * any way other than via the returned list.
1051 tim 1.1 *
1052 jsr166 1.35 * @param fromIndex low endpoint (inclusive) of the subList
1053     * @param toIndex high endpoint (exclusive) of the subList
1054     * @return a view of the specified range within this list
1055     * @throws IndexOutOfBoundsException {@inheritDoc}
1056 tim 1.1 */
1057 dl 1.42 public List<E> subList(int fromIndex, int toIndex) {
1058 jsr166 1.67 final ReentrantLock lock = this.lock;
1059     lock.lock();
1060     try {
1061     Object[] elements = getArray();
1062     int len = elements.length;
1063     if (fromIndex < 0 || toIndex > len || fromIndex > toIndex)
1064     throw new IndexOutOfBoundsException();
1065     return new COWSubList<E>(this, fromIndex, toIndex);
1066     } finally {
1067     lock.unlock();
1068     }
1069 tim 1.1 }
1070    
1071 dl 1.42 /**
1072     * Sublist for CopyOnWriteArrayList.
1073     * This class extends AbstractList merely for convenience, to
1074     * avoid having to define addAll, etc. This doesn't hurt, but
1075     * is wasteful. This class does not need or use modCount
1076     * mechanics in AbstractList, but does need to check for
1077     * concurrent modification using similar mechanics. On each
1078     * operation, the array that we expect the backing list to use
1079     * is checked and updated. Since we do this for all of the
1080     * base operations invoked by those defined in AbstractList,
1081     * all is well. While inefficient, this is not worth
1082     * improving. The kinds of list operations inherited from
1083     * AbstractList are already so slow on COW sublists that
1084     * adding a bit more space/time doesn't seem even noticeable.
1085     */
1086 jsr166 1.66 private static class COWSubList<E>
1087 jsr166 1.67 extends AbstractList<E>
1088     implements RandomAccess
1089 jsr166 1.66 {
1090 tim 1.1 private final CopyOnWriteArrayList<E> l;
1091     private final int offset;
1092     private int size;
1093 dl 1.41 private Object[] expectedArray;
1094 tim 1.1
1095 jsr166 1.45 // only call this holding l's lock
1096 jsr166 1.66 COWSubList(CopyOnWriteArrayList<E> list,
1097 jsr166 1.67 int fromIndex, int toIndex) {
1098 tim 1.1 l = list;
1099 dl 1.40 expectedArray = l.getArray();
1100 tim 1.1 offset = fromIndex;
1101     size = toIndex - fromIndex;
1102     }
1103    
1104     // only call this holding l's lock
1105     private void checkForComodification() {
1106 dl 1.40 if (l.getArray() != expectedArray)
1107 tim 1.1 throw new ConcurrentModificationException();
1108     }
1109    
1110     // only call this holding l's lock
1111     private void rangeCheck(int index) {
1112 jsr166 1.45 if (index<0 || index>=size)
1113     throw new IndexOutOfBoundsException("Index: "+index+
1114 jsr166 1.67 ",Size: "+size);
1115 tim 1.1 }
1116    
1117     public E set(int index, E element) {
1118 jsr166 1.67 final ReentrantLock lock = l.lock;
1119     lock.lock();
1120     try {
1121 tim 1.1 rangeCheck(index);
1122     checkForComodification();
1123 jsr166 1.45 E x = l.set(index+offset, element);
1124 dl 1.40 expectedArray = l.getArray();
1125 tim 1.1 return x;
1126 jsr166 1.67 } finally {
1127     lock.unlock();
1128     }
1129 tim 1.1 }
1130    
1131     public E get(int index) {
1132 jsr166 1.67 final ReentrantLock lock = l.lock;
1133     lock.lock();
1134     try {
1135 tim 1.1 rangeCheck(index);
1136     checkForComodification();
1137 jsr166 1.45 return l.get(index+offset);
1138 jsr166 1.67 } finally {
1139     lock.unlock();
1140     }
1141 tim 1.1 }
1142    
1143     public int size() {
1144 jsr166 1.67 final ReentrantLock lock = l.lock;
1145     lock.lock();
1146     try {
1147 tim 1.1 checkForComodification();
1148     return size;
1149 jsr166 1.67 } finally {
1150     lock.unlock();
1151     }
1152 tim 1.1 }
1153    
1154     public void add(int index, E element) {
1155 jsr166 1.67 final ReentrantLock lock = l.lock;
1156     lock.lock();
1157     try {
1158 tim 1.1 checkForComodification();
1159     if (index<0 || index>size)
1160     throw new IndexOutOfBoundsException();
1161 jsr166 1.45 l.add(index+offset, element);
1162 dl 1.40 expectedArray = l.getArray();
1163 tim 1.1 size++;
1164 jsr166 1.67 } finally {
1165     lock.unlock();
1166     }
1167 tim 1.1 }
1168    
1169 dl 1.13 public void clear() {
1170 jsr166 1.67 final ReentrantLock lock = l.lock;
1171     lock.lock();
1172     try {
1173 dl 1.13 checkForComodification();
1174     l.removeRange(offset, offset+size);
1175 dl 1.40 expectedArray = l.getArray();
1176 dl 1.13 size = 0;
1177 jsr166 1.67 } finally {
1178     lock.unlock();
1179     }
1180 dl 1.13 }
1181    
1182 tim 1.1 public E remove(int index) {
1183 jsr166 1.67 final ReentrantLock lock = l.lock;
1184     lock.lock();
1185     try {
1186 tim 1.1 rangeCheck(index);
1187     checkForComodification();
1188 jsr166 1.45 E result = l.remove(index+offset);
1189 dl 1.40 expectedArray = l.getArray();
1190 tim 1.1 size--;
1191     return result;
1192 jsr166 1.67 } finally {
1193     lock.unlock();
1194     }
1195 tim 1.1 }
1196    
1197 jsr166 1.66 public boolean remove(Object o) {
1198 jsr166 1.67 int index = indexOf(o);
1199     if (index == -1)
1200     return false;
1201     remove(index);
1202     return true;
1203 jsr166 1.66 }
1204    
1205 tim 1.1 public Iterator<E> iterator() {
1206 jsr166 1.67 final ReentrantLock lock = l.lock;
1207     lock.lock();
1208     try {
1209 tim 1.1 checkForComodification();
1210 tim 1.8 return new COWSubListIterator<E>(l, 0, offset, size);
1211 jsr166 1.67 } finally {
1212     lock.unlock();
1213     }
1214 tim 1.1 }
1215    
1216     public ListIterator<E> listIterator(final int index) {
1217 jsr166 1.67 final ReentrantLock lock = l.lock;
1218     lock.lock();
1219     try {
1220 tim 1.1 checkForComodification();
1221     if (index<0 || index>size)
1222 dl 1.40 throw new IndexOutOfBoundsException("Index: "+index+
1223 jsr166 1.67 ", Size: "+size);
1224 tim 1.8 return new COWSubListIterator<E>(l, index, offset, size);
1225 jsr166 1.67 } finally {
1226     lock.unlock();
1227     }
1228 tim 1.1 }
1229    
1230 tim 1.7 public List<E> subList(int fromIndex, int toIndex) {
1231 jsr166 1.67 final ReentrantLock lock = l.lock;
1232     lock.lock();
1233     try {
1234 tim 1.7 checkForComodification();
1235     if (fromIndex<0 || toIndex>size)
1236     throw new IndexOutOfBoundsException();
1237 dl 1.41 return new COWSubList<E>(l, fromIndex + offset,
1238 jsr166 1.67 toIndex + offset);
1239     } finally {
1240     lock.unlock();
1241     }
1242 tim 1.7 }
1243 tim 1.1
1244 tim 1.7 }
1245 tim 1.1
1246    
1247 tim 1.7 private static class COWSubListIterator<E> implements ListIterator<E> {
1248     private final ListIterator<E> i;
1249     private final int index;
1250     private final int offset;
1251     private final int size;
1252 jsr166 1.66
1253 jsr166 1.67 COWSubListIterator(List<E> l, int index, int offset,
1254     int size) {
1255 tim 1.7 this.index = index;
1256     this.offset = offset;
1257     this.size = size;
1258 jsr166 1.45 i = l.listIterator(index+offset);
1259 tim 1.7 }
1260 tim 1.1
1261 tim 1.7 public boolean hasNext() {
1262     return nextIndex() < size;
1263     }
1264 tim 1.1
1265 tim 1.7 public E next() {
1266     if (hasNext())
1267     return i.next();
1268     else
1269     throw new NoSuchElementException();
1270     }
1271 tim 1.1
1272 tim 1.7 public boolean hasPrevious() {
1273     return previousIndex() >= 0;
1274     }
1275 tim 1.1
1276 tim 1.7 public E previous() {
1277     if (hasPrevious())
1278     return i.previous();
1279     else
1280     throw new NoSuchElementException();
1281     }
1282 tim 1.1
1283 tim 1.7 public int nextIndex() {
1284     return i.nextIndex() - offset;
1285     }
1286 tim 1.1
1287 tim 1.7 public int previousIndex() {
1288     return i.previousIndex() - offset;
1289 tim 1.1 }
1290    
1291 tim 1.7 public void remove() {
1292     throw new UnsupportedOperationException();
1293     }
1294 tim 1.1
1295 jsr166 1.33 public void set(E e) {
1296 tim 1.7 throw new UnsupportedOperationException();
1297 tim 1.1 }
1298    
1299 jsr166 1.33 public void add(E e) {
1300 tim 1.7 throw new UnsupportedOperationException();
1301     }
1302 tim 1.1 }
1303    
1304 dl 1.42 // Support for resetting lock while deserializing
1305 dl 1.72 private void resetLock() {
1306     UNSAFE.putObjectVolatile(this, lockOffset, new ReentrantLock());
1307     }
1308     private static final sun.misc.Unsafe UNSAFE;
1309 dl 1.42 private static final long lockOffset;
1310     static {
1311     try {
1312 dl 1.72 UNSAFE = sun.misc.Unsafe.getUnsafe();
1313 jsr166 1.76 Class<?> k = CopyOnWriteArrayList.class;
1314 dl 1.72 lockOffset = UNSAFE.objectFieldOffset
1315     (k.getDeclaredField("lock"));
1316     } catch (Exception e) {
1317     throw new Error(e);
1318     }
1319 dl 1.42 }
1320 tim 1.1 }