ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.42
Committed: Sun Jun 5 13:53:25 2005 UTC (19 years ago) by dl
Branch: MAIN
Changes since 1.41: +368 -225 lines
Log Message:
Use ReentrantLock

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