ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CopyOnWriteArrayList.java
Revision: 1.12
Committed: Tue Aug 26 13:07:36 2003 UTC (20 years, 9 months ago) by dl
Branch: MAIN
Changes since 1.11: +80 -87 lines
Log Message:
Style cleanups to COWList; CyclicBarrier broken barriers now Fast-fail

File Contents

# User Rev Content
1 dl 1.2 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3 tim 1.7 * Expert Group. Adapted and released under explicit permission
4 dl 1.3 * from JDK1.2 ArrayList.java which carries the following copyright:
5     *
6     * Copyright 1997 by Sun Microsystems, Inc.,
7     * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
8     * All rights reserved.
9     *
10     * This software is the confidential and proprietary information
11     * of Sun Microsystems, Inc. ("Confidential Information"). You
12     * shall not disclose such Confidential Information and shall use
13     * it only in accordance with the terms of the license agreement
14     * you entered into with Sun.
15 dl 1.2 */
16    
17 tim 1.1 package java.util.concurrent;
18     import java.util.*;
19    
20     /**
21 dl 1.4 * A variant of {@link java.util.ArrayList} in which all mutative
22     * operations (add, set, and so on) are implemented by making a fresh
23     * copy of the underlying array. <p>
24 tim 1.1 *
25 dl 1.12 * This is ordinarily too costly, but may be <em>more</em> efficient
26     * than alternatives when traversal operations vastly outnumber
27     * mutations, and is useful when you cannot or don't want to
28     * synchronize traversals, yet need to preclude interference among
29     * concurrent threads. The iterator method uses a reference to the
30     * state of the array at the point that the iterator was created. This
31     * array never changes during the lifetime of the iterator, so
32     * interference is impossible and the iterator is guaranteed not to
33     * throw <tt>ConcurrentModificationException</tt>. The iterator will
34     * not reflect additions, removals, or changes to the list since the
35     * iterator was created. Element-changing operations on iterators
36     * themselves (remove, set, and add) are not supported. These methods
37     * throw <tt>UnsupportedOperationException</tt>.
38 dl 1.6 * @since 1.5
39     * @author Doug Lea
40     */
41 tim 1.1 public class CopyOnWriteArrayList<E>
42     implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
43 dl 1.11 private static final long serialVersionUID = 8673264195747942595L;
44 tim 1.1
45     /**
46 dl 1.6 * The held array. Directly accessed only within synchronized
47 tim 1.1 * methods
48     */
49 dl 1.12 private volatile transient E[] array;
50 tim 1.1
51     /**
52     * Accessor to the array intended to be called from
53     * within unsynchronized read-only methods
54     **/
55 dl 1.12 private E[] array() { return array; }
56 tim 1.1
57     /**
58 tim 1.9 * Constructs an empty list.
59 tim 1.1 */
60     public CopyOnWriteArrayList() {
61 dl 1.12 array = (E[]) new Object[0];
62 tim 1.1 }
63    
64     /**
65     * Constructs an list containing the elements of the specified
66     * Collection, in the order they are returned by the Collection's
67     * iterator.
68 dl 1.6 * @param c the collection of initially held elements
69 tim 1.1 */
70     public CopyOnWriteArrayList(Collection<E> c) {
71 dl 1.12 array = (E[]) new Object[c.size()];
72 tim 1.1 Iterator<E> i = c.iterator();
73     int size = 0;
74     while (i.hasNext())
75 dl 1.12 array[size++] = i.next();
76 tim 1.1 }
77    
78     /**
79 tim 1.9 * Create a new CopyOnWriteArrayList holding a copy of given array.
80     *
81     * @param toCopyIn the array (a copy of this array is used as the
82     * internal array)
83 tim 1.1 **/
84     public CopyOnWriteArrayList(E[] toCopyIn) {
85     copyIn(toCopyIn, 0, toCopyIn.length);
86     }
87    
88     /**
89     * Replace the held array with a copy of the <code>n</code>
90 dl 1.12 * elements of the provided array, starting at position
91     * <code>first</code>. To copy an entire array, call with
92     * arguments (array, 0, array.length).
93 tim 1.1 * @param toCopyIn the array. A copy of the indicated elements of
94     * this array is used as the
95     * internal array.
96     * @param first The index of first position of the array to
97     * start copying from.
98     * @param n the number of elements to copy. This will be the new size of
99     * the list.
100     **/
101     private synchronized void copyIn(E[] toCopyIn, int first, int n) {
102 dl 1.12 array = (E[]) new Object[n];
103     System.arraycopy(toCopyIn, first, array, 0, n);
104 tim 1.1 }
105    
106     /**
107     * Returns the number of components in this list.
108     *
109     * @return the number of components in this list.
110     */
111     public int size() {
112     return array().length;
113     }
114    
115     /**
116     * Tests if this list has no components.
117     *
118     * @return <code>true</code> if this list has no components;
119     * <code>false</code> otherwise.
120     */
121     public boolean isEmpty() {
122     return size() == 0;
123     }
124    
125     /**
126     * Returns true if this list contains the specified element.
127     *
128 dl 1.6 * @param elem element whose presence in this List is to be tested.
129 tim 1.1 */
130     public boolean contains(Object elem) {
131     E[] elementData = array();
132     int len = elementData.length;
133     return indexOf(elem, elementData, len) >= 0;
134     }
135    
136     /**
137     * Searches for the first occurence of the given argument, testing
138     * for equality using the <code>equals</code> method.
139     *
140     * @param elem an object.
141     * @return the index of the first occurrence of the argument in this
142     * list; returns <code>-1</code> if the object is not found.
143     * @see Object#equals(Object)
144     */
145     public int indexOf(Object elem) {
146     E[] elementData = array();
147     int len = elementData.length;
148     return indexOf(elem, elementData, len);
149     }
150    
151    
152     /**
153     * static version allows repeated call without needed
154     * to grab lock for array each time
155     **/
156     private static int indexOf(Object elem, Object[] elementData, int len) {
157     if (elem == null) {
158     for (int i = 0; i < len; i++)
159     if (elementData[i]==null)
160     return i;
161     } else {
162     for (int i = 0; i < len; i++)
163     if (elem.equals(elementData[i]))
164     return i;
165     }
166     return -1;
167     }
168    
169     /**
170     * Searches for the first occurence of the given argument, beginning
171     * the search at <code>index</code>, and testing for equality using
172     * the <code>equals</code> method.
173     *
174     * @param elem an object.
175     * @param index the index to start searching from.
176     * @return the index of the first occurrence of the object argument in
177     * this List at position <code>index</code> or later in the
178     * List; returns <code>-1</code> if the object is not found.
179     * @see Object#equals(Object)
180     */
181     public int indexOf(E elem, int index) {
182     E[] elementData = array();
183     int elementCount = elementData.length;
184    
185     if (elem == null) {
186     for (int i = index ; i < elementCount ; i++)
187     if (elementData[i]==null)
188     return i;
189     } else {
190     for (int i = index ; i < elementCount ; i++)
191     if (elem.equals(elementData[i]))
192     return i;
193     }
194     return -1;
195     }
196    
197     /**
198     * Returns the index of the last occurrence of the specified object in
199     * this list.
200     *
201     * @param elem the desired component.
202     * @return the index of the last occurrence of the specified object in
203     * this list; returns -1 if the object is not found.
204     */
205     public int lastIndexOf(Object elem) {
206     E[] elementData = array();
207     int len = elementData.length;
208     return lastIndexOf(elem, elementData, len);
209     }
210    
211     private static int lastIndexOf(Object elem, Object[] elementData, int len) {
212     if (elem == null) {
213     for (int i = len-1; i >= 0; i--)
214     if (elementData[i]==null)
215     return i;
216     } else {
217     for (int i = len-1; i >= 0; i--)
218     if (elem.equals(elementData[i]))
219     return i;
220     }
221     return -1;
222     }
223    
224     /**
225     * Searches backwards for the specified object, starting from the
226     * specified index, and returns an index to it.
227     *
228     * @param elem the desired component.
229     * @param index the index to start searching from.
230     * @return the index of the last occurrence of the specified object in this
231     * List at position less than index in the List;
232     * -1 if the object is not found.
233     */
234     public int lastIndexOf(E elem, int index) {
235     // needed in order to compile on 1.2b3
236     E[] elementData = array();
237     if (elem == null) {
238     for (int i = index; i >= 0; i--)
239     if (elementData[i]==null)
240     return i;
241     } else {
242     for (int i = index; i >= 0; i--)
243     if (elem.equals(elementData[i]))
244     return i;
245     }
246     return -1;
247     }
248    
249     /**
250     * Returns a shallow copy of this list. (The elements themselves
251     * are not copied.)
252     *
253     * @return a clone of this list.
254     */
255     public Object clone() {
256     try {
257     E[] elementData = array();
258 tim 1.8 CopyOnWriteArrayList<E> v = (CopyOnWriteArrayList<E>)super.clone();
259 dl 1.12 v.array = (E[]) new Object[elementData.length];
260     System.arraycopy(elementData, 0, v.array, 0, elementData.length);
261 tim 1.1 return v;
262     } catch (CloneNotSupportedException e) {
263     // this shouldn't happen, since we are Cloneable
264     throw new InternalError();
265     }
266     }
267    
268     /**
269     * Returns an array containing all of the elements in this list
270     * in the correct order.
271     */
272     public Object[] toArray() {
273     Object[] elementData = array();
274     Object[] result = new Object[elementData.length];
275     System.arraycopy(elementData, 0, result, 0, elementData.length);
276     return result;
277     }
278    
279     /**
280     * Returns an array containing all of the elements in this list in the
281     * correct order. The runtime type of the returned array is that of the
282     * specified array. If the list fits in the specified array, it is
283     * returned therein. Otherwise, a new array is allocated with the runtime
284     * type of the specified array and the size of this list.
285     * <p>
286     * If the list fits in the specified array with room to spare
287     * (i.e., the array has more elements than the list),
288     * the element in the array immediately following the end of the
289     * collection is set to null. This is useful in determining the length
290     * of the list <em>only</em> if the caller knows that the list
291     * does not contain any null elements.
292     *
293     * @param a the array into which the elements of the list are to
294     * be stored, if it is big enough; otherwise, a new array of the
295     * same runtime type is allocated for this purpose.
296     * @return an array containing the elements of the list.
297 dl 1.6 * @throws ArrayStoreException the runtime type of a is not a supertype
298 tim 1.1 * of the runtime type of every element in this list.
299     */
300     public <T> T[] toArray(T a[]) {
301     E[] elementData = array();
302    
303     if (a.length < elementData.length)
304     a = (T[])
305     java.lang.reflect.Array.newInstance(a.getClass().getComponentType(),
306     elementData.length);
307    
308     System.arraycopy(elementData, 0, a, 0, elementData.length);
309    
310     if (a.length > elementData.length)
311     a[elementData.length] = null;
312    
313     return a;
314     }
315    
316     // Positional Access Operations
317    
318     /**
319     * Returns the element at the specified position in this list.
320     *
321     * @param index index of element to return.
322 dl 1.6 * @return the element
323     * @throws IndexOutOfBoundsException index is out of range (index
324 tim 1.1 * &lt; 0 || index &gt;= size()).
325     */
326     public E get(int index) {
327     E[] elementData = array();
328     rangeCheck(index, elementData.length);
329     return elementData[index];
330     }
331    
332     /**
333     * Replaces the element at the specified position in this list with
334     * the specified element.
335     *
336     * @param index index of element to replace.
337     * @param element element to be stored at the specified position.
338     * @return the element previously at the specified position.
339 dl 1.6 * @throws IndexOutOfBoundsException index out of range
340 tim 1.1 * (index &lt; 0 || index &gt;= size()).
341     */
342     public synchronized E set(int index, E element) {
343 dl 1.12 int len = array.length;
344 tim 1.1 rangeCheck(index, len);
345 dl 1.12 E oldValue = array[index];
346 tim 1.1
347     boolean same = (oldValue == element ||
348     (element != null && element.equals(oldValue)));
349     if (!same) {
350 tim 1.7 E[] newArray = (E[]) new Object[len];
351 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
352 tim 1.1 newArray[index] = element;
353 dl 1.12 array = newArray;
354 tim 1.1 }
355     return oldValue;
356     }
357    
358     /**
359     * Appends the specified element to the end of this list.
360     *
361     * @param element element to be appended to this list.
362     * @return true (as per the general contract of Collection.add).
363     */
364     public synchronized boolean add(E element) {
365 dl 1.12 int len = array.length;
366 tim 1.7 E[] newArray = (E[]) new Object[len+1];
367 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
368 tim 1.1 newArray[len] = element;
369 dl 1.12 array = newArray;
370 tim 1.1 return true;
371     }
372    
373     /**
374     * Inserts the specified element at the specified position in this
375     * list. Shifts the element currently at that position (if any) and
376     * any subsequent elements to the right (adds one to their indices).
377     *
378     * @param index index at which the specified element is to be inserted.
379     * @param element element to be inserted.
380 dl 1.6 * @throws IndexOutOfBoundsException index is out of range
381 tim 1.1 * (index &lt; 0 || index &gt; size()).
382     */
383     public synchronized void add(int index, E element) {
384 dl 1.12 int len = array.length;
385 tim 1.1 if (index > len || index < 0)
386     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+len);
387    
388 tim 1.7 E[] newArray = (E[]) new Object[len+1];
389 dl 1.12 System.arraycopy(array, 0, newArray, 0, index);
390 tim 1.1 newArray[index] = element;
391 dl 1.12 System.arraycopy(array, index, newArray, index+1, len - index);
392     array = newArray;
393 tim 1.1 }
394    
395     /**
396     * Removes the element at the specified position in this list.
397     * Shifts any subsequent elements to the left (subtracts one from their
398     * indices). Returns the element that was removed from the list.
399     *
400 dl 1.6 * @throws IndexOutOfBoundsException index out of range (index
401 tim 1.1 * &lt; 0 || index &gt;= size()).
402     * @param index the index of the element to removed.
403     */
404     public synchronized E remove(int index) {
405 dl 1.12 int len = array.length;
406 tim 1.1 rangeCheck(index, len);
407 dl 1.12 E oldValue = array[index];
408 tim 1.7 E[] newArray = (E[]) new Object[len-1];
409 dl 1.12 System.arraycopy(array, 0, newArray, 0, index);
410 tim 1.1 int numMoved = len - index - 1;
411     if (numMoved > 0)
412 dl 1.12 System.arraycopy(array, index+1, newArray, index, numMoved);
413     array = newArray;
414 tim 1.1 return oldValue;
415     }
416    
417     /**
418     * Removes a single instance of the specified element from this Collection,
419     * if it is present (optional operation). More formally, removes an
420     * element <code>e</code> such that <code>(o==null ? e==null :
421     * o.equals(e))</code>, if the Collection contains one or more such
422     * elements. Returns true if the Collection contained the specified
423     * element (or equivalently, if the Collection changed as a result of the
424     * call).
425     *
426     * @param element element to be removed from this Collection, if present.
427     * @return true if the Collection changed as a result of the call.
428     */
429     public synchronized boolean remove(Object element) {
430 dl 1.12 int len = array.length;
431 tim 1.1 if (len == 0) return false;
432    
433     // Copy while searching for element to remove
434     // This wins in the normal case of element being present
435    
436     int newlen = len-1;
437 tim 1.7 E[] newArray = (E[]) new Object[newlen];
438 tim 1.1
439     for (int i = 0; i < newlen; ++i) {
440 dl 1.12 if (element == array[i] ||
441     (element != null && element.equals(array[i]))) {
442 tim 1.1 // found one; copy remaining and exit
443 dl 1.12 for (int k = i + 1; k < len; ++k) newArray[k-1] = array[k];
444     array = newArray;
445 tim 1.1 return true;
446 tim 1.10 } else
447 dl 1.12 newArray[i] = array[i];
448 tim 1.1 }
449     // special handling for last cell
450    
451 dl 1.12 if (element == array[newlen] ||
452     (element != null && element.equals(array[newlen]))) {
453     array = newArray;
454 tim 1.1 return true;
455 tim 1.10 } else
456 tim 1.1 return false; // throw away copy
457    
458     }
459    
460    
461     /**
462     * Removes from this List all of the elements whose index is between
463     * fromIndex, inclusive and toIndex, exclusive. Shifts any succeeding
464     * elements to the left (reduces their index).
465     * This call shortens the List by (toIndex - fromIndex) elements. (If
466     * toIndex==fromIndex, this operation has no effect.)
467     *
468     * @param fromIndex index of first element to be removed.
469 dl 1.6 * @param toIndex index after last element to be removed.
470     * @throws IndexOutOfBoundsException fromIndex or toIndex out of
471 tim 1.1 * range (fromIndex &lt; 0 || fromIndex &gt;= size() || toIndex
472     * &gt; size() || toIndex &lt; fromIndex).
473     */
474     private synchronized void removeRange(int fromIndex, int toIndex) {
475 dl 1.12 int len = array.length;
476 tim 1.1
477     if (fromIndex < 0 || fromIndex >= len ||
478     toIndex > len || toIndex < fromIndex)
479     throw new IndexOutOfBoundsException();
480    
481     int numMoved = len - toIndex;
482     int newlen = len - (toIndex-fromIndex);
483 tim 1.7 E[] newArray = (E[]) new Object[newlen];
484 dl 1.12 System.arraycopy(array, 0, newArray, 0, fromIndex);
485     System.arraycopy(array, toIndex, newArray, fromIndex, numMoved);
486     array = newArray;
487 tim 1.1 }
488    
489    
490     /**
491     * Append the element if not present.
492     * @param element element to be added to this Collection, if absent.
493     * @return true if added
494     **/
495     public synchronized boolean addIfAbsent(E element) {
496     // Copy while checking if already present.
497     // This wins in the most common case where it is not present
498 dl 1.12 int len = array.length;
499 tim 1.7 E[] newArray = (E[]) new Object[len + 1];
500 tim 1.1 for (int i = 0; i < len; ++i) {
501 dl 1.12 if (element == array[i] ||
502     (element != null && element.equals(array[i])))
503 tim 1.1 return false; // exit, throwing away copy
504     else
505 dl 1.12 newArray[i] = array[i];
506 tim 1.1 }
507     newArray[len] = element;
508 dl 1.12 array = newArray;
509 tim 1.1 return true;
510     }
511    
512     /**
513     * Returns true if this Collection contains all of the elements in the
514     * specified Collection.
515     * <p>
516     * This implementation iterates over the specified Collection, checking
517     * each element returned by the Iterator in turn to see if it's
518     * contained in this Collection. If all elements are so contained
519     * true is returned, otherwise false.
520 dl 1.6 * @param c the collection
521     * @return true if all elements are contained
522 tim 1.1 */
523 tim 1.7 public boolean containsAll(Collection<?> c) {
524 tim 1.1 E[] elementData = array();
525     int len = elementData.length;
526 tim 1.7 Iterator e = c.iterator();
527 tim 1.1 while (e.hasNext())
528 tim 1.7 if (indexOf((E) e.next(), elementData, len) < 0)
529 tim 1.1 return false;
530    
531     return true;
532     }
533    
534    
535     /**
536     * Removes from this Collection all of its elements that are contained in
537     * the specified Collection. This is a particularly expensive operation
538     * in this class because of the need for an internal temporary array.
539     * <p>
540     *
541 dl 1.6 * @param c the collection
542 tim 1.1 * @return true if this Collection changed as a result of the call.
543     */
544 tim 1.7 public synchronized boolean removeAll(Collection<?> c) {
545 dl 1.12 E[] elementData = array;
546 tim 1.1 int len = elementData.length;
547     if (len == 0) return false;
548    
549     // temp array holds those elements we know we want to keep
550 tim 1.7 E[] temp = (E[]) new Object[len];
551 tim 1.1 int newlen = 0;
552     for (int i = 0; i < len; ++i) {
553     E element = elementData[i];
554     if (!c.contains(element)) {
555     temp[newlen++] = element;
556     }
557     }
558    
559     if (newlen == len) return false;
560    
561     // copy temp as new array
562 tim 1.7 E[] newArray = (E[]) new Object[newlen];
563 tim 1.1 System.arraycopy(temp, 0, newArray, 0, newlen);
564 dl 1.12 array = newArray;
565 tim 1.1 return true;
566     }
567    
568     /**
569     * Retains only the elements in this Collection that are contained in the
570     * specified Collection (optional operation). In other words, removes from
571     * this Collection all of its elements that are not contained in the
572     * specified Collection.
573 dl 1.6 * @param c the collection
574 tim 1.1 * @return true if this Collection changed as a result of the call.
575     */
576 tim 1.7 public synchronized boolean retainAll(Collection<?> c) {
577 dl 1.12 E[] elementData = array;
578 tim 1.1 int len = elementData.length;
579     if (len == 0) return false;
580    
581 tim 1.7 E[] temp = (E[]) new Object[len];
582 tim 1.1 int newlen = 0;
583     for (int i = 0; i < len; ++i) {
584     E element = elementData[i];
585     if (c.contains(element)) {
586     temp[newlen++] = element;
587     }
588     }
589    
590     if (newlen == len) return false;
591    
592 tim 1.7 E[] newArray = (E[]) new Object[newlen];
593 tim 1.1 System.arraycopy(temp, 0, newArray, 0, newlen);
594 dl 1.12 array = newArray;
595 tim 1.1 return true;
596     }
597    
598     /**
599     * Appends all of the elements in the specified Collection that
600     * are not already contained in this list, to the end of
601     * this list, in the order that they are returned by the
602     * specified Collection's Iterator.
603     *
604     * @param c elements to be added into this list.
605     * @return the number of elements added
606     */
607 tim 1.7 public synchronized int addAllAbsent(Collection<? extends E> c) {
608 tim 1.1 int numNew = c.size();
609     if (numNew == 0) return 0;
610    
611 dl 1.12 E[] elementData = array;
612 tim 1.1 int len = elementData.length;
613    
614 tim 1.7 E[] temp = (E[]) new Object[numNew];
615 tim 1.1 int added = 0;
616 tim 1.7 Iterator e = c.iterator();
617 tim 1.1 while (e.hasNext()) {
618 tim 1.7 E element = (E) e.next();
619 tim 1.1 if (indexOf(element, elementData, len) < 0) {
620     if (indexOf(element, temp, added) < 0) {
621     temp[added++] = element;
622     }
623     }
624     }
625    
626     if (added == 0) return 0;
627    
628 tim 1.7 E[] newArray = (E[]) new Object[len+added];
629 tim 1.1 System.arraycopy(elementData, 0, newArray, 0, len);
630     System.arraycopy(temp, 0, newArray, len, added);
631 dl 1.12 array = newArray;
632 tim 1.1 return added;
633     }
634    
635     /**
636     * Removes all of the elements from this list.
637     *
638     */
639     public synchronized void clear() {
640 dl 1.12 array = (E[]) new Object[0];
641 tim 1.1 }
642    
643     /**
644     * Appends all of the elements in the specified Collection to the end of
645     * this list, in the order that they are returned by the
646     * specified Collection's Iterator.
647     *
648     * @param c elements to be inserted into this list.
649 dl 1.6 * @return true if any elements are added
650 tim 1.1 */
651 tim 1.7 public synchronized boolean addAll(Collection<? extends E> c) {
652 tim 1.1 int numNew = c.size();
653     if (numNew == 0) return false;
654    
655 dl 1.12 int len = array.length;
656 tim 1.7 E[] newArray = (E[]) new Object[len+numNew];
657 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
658 tim 1.7 Iterator e = c.iterator();
659 tim 1.1 for (int i=0; i<numNew; i++)
660 tim 1.7 newArray[len++] = (E) e.next();
661 dl 1.12 array = newArray;
662 tim 1.1
663     return true;
664     }
665    
666     /**
667     * Inserts all of the elements in the specified Collection into this
668     * list, starting at the specified position. Shifts the element
669     * currently at that position (if any) and any subsequent elements to
670     * the right (increases their indices). The new elements will appear
671     * in the list in the order that they are returned by the
672     * specified Collection's iterator.
673     *
674     * @param index index at which to insert first element
675     * from the specified collection.
676     * @param c elements to be inserted into this list.
677 dl 1.6 * @throws IndexOutOfBoundsException index out of range (index
678 tim 1.1 * &lt; 0 || index &gt; size()).
679 dl 1.6 * @return true if any elements are added
680 tim 1.1 */
681 tim 1.7 public synchronized boolean addAll(int index, Collection<? extends E> c) {
682 dl 1.12 int len = array.length;
683 tim 1.1 if (index > len || index < 0)
684     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+len);
685    
686     int numNew = c.size();
687     if (numNew == 0) return false;
688    
689 tim 1.7 E[] newArray = (E[]) new Object[len+numNew];
690 dl 1.12 System.arraycopy(array, 0, newArray, 0, len);
691 tim 1.1 int numMoved = len - index;
692     if (numMoved > 0)
693 dl 1.12 System.arraycopy(array, index, newArray, index + numNew, numMoved);
694 tim 1.7 Iterator e = c.iterator();
695 tim 1.1 for (int i=0; i<numNew; i++)
696 tim 1.7 newArray[index++] = (E) e.next();
697 dl 1.12 array = newArray;
698 tim 1.1
699     return true;
700     }
701    
702     /**
703     * Check if the given index is in range. If not, throw an appropriate
704     * runtime exception.
705     */
706     private void rangeCheck(int index, int length) {
707     if (index >= length || index < 0)
708     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+ length);
709     }
710    
711     /**
712     * Save the state of the list to a stream (i.e., serialize it).
713     *
714     * @serialData The length of the array backing the list is emitted
715     * (int), followed by all of its elements (each an Object)
716     * in the proper order.
717 dl 1.6 * @param s the stream
718 tim 1.1 */
719     private void writeObject(java.io.ObjectOutputStream s)
720     throws java.io.IOException{
721    
722     // Write out element count, and any hidden stuff
723     s.defaultWriteObject();
724    
725     E[] elementData = array();
726     // Write out array length
727     s.writeInt(elementData.length);
728    
729     // Write out all elements in the proper order.
730     for (int i=0; i<elementData.length; i++)
731     s.writeObject(elementData[i]);
732     }
733    
734     /**
735     * Reconstitute the list from a stream (i.e., deserialize it).
736 dl 1.6 * @param s the stream
737 tim 1.1 */
738 dl 1.12 private void readObject(java.io.ObjectInputStream s)
739 tim 1.1 throws java.io.IOException, ClassNotFoundException {
740    
741     // Read in size, and any hidden stuff
742     s.defaultReadObject();
743    
744     // Read in array length and allocate array
745     int arrayLength = s.readInt();
746 tim 1.7 E[] elementData = (E[]) new Object[arrayLength];
747 tim 1.1
748     // Read in all elements in the proper order.
749     for (int i=0; i<elementData.length; i++)
750     elementData[i] = (E) s.readObject();
751 dl 1.12 array = elementData;
752 tim 1.1 }
753    
754     /**
755     * Returns a string representation of this Collection, containing
756     * the String representation of each element.
757     */
758     public String toString() {
759     StringBuffer buf = new StringBuffer();
760     Iterator e = iterator();
761     buf.append("[");
762     int maxIndex = size() - 1;
763     for (int i = 0; i <= maxIndex; i++) {
764     buf.append(String.valueOf(e.next()));
765     if (i < maxIndex)
766     buf.append(", ");
767     }
768     buf.append("]");
769     return buf.toString();
770     }
771    
772    
773     /**
774     * Compares the specified Object with this List for equality. Returns true
775     * if and only if the specified Object is also a List, both Lists have the
776     * same size, and all corresponding pairs of elements in the two Lists are
777     * <em>equal</em>. (Two elements <code>e1</code> and <code>e2</code> are
778     * <em>equal</em> if <code>(e1==null ? e2==null : e1.equals(e2))</code>.)
779     * In other words, two Lists are defined to be equal if they contain the
780     * same elements in the same order.
781     * <p>
782     * This implementation first checks if the specified object is this
783     * List. If so, it returns true; if not, it checks if the specified
784     * object is a List. If not, it returns false; if so, it iterates over
785     * both lists, comparing corresponding pairs of elements. If any
786     * comparison returns false, this method returns false. If either
787     * Iterator runs out of elements before before the other it returns false
788     * (as the Lists are of unequal length); otherwise it returns true when
789     * the iterations complete.
790     *
791     * @param o the Object to be compared for equality with this List.
792     * @return true if the specified Object is equal to this List.
793     */
794     public boolean equals(Object o) {
795     if (o == this)
796     return true;
797     if (!(o instanceof List))
798     return false;
799    
800 tim 1.8 List<E> l2 = (List<E>)(o);
801 tim 1.1 if (size() != l2.size())
802     return false;
803    
804     ListIterator<E> e1 = listIterator();
805     ListIterator<E> e2 = l2.listIterator();
806     while(e1.hasNext()) {
807     E o1 = e1.next();
808     E o2 = e2.next();
809     if (!(o1==null ? o2==null : o1.equals(o2)))
810     return false;
811     }
812     return true;
813     }
814    
815     /**
816     * Returns the hash code value for this List.
817     * <p>
818     * This implementation uses exactly the code that is used to define
819     * the List hash function in the documentation for List.hashCode.
820     */
821     public int hashCode() {
822     int hashCode = 1;
823     Iterator<E> i = iterator();
824     while (i.hasNext()) {
825     E obj = i.next();
826     hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
827     }
828     return hashCode;
829     }
830    
831     /**
832     * Returns an Iterator over the elements contained in this collection.
833     * The iterator provides a snapshot of the state of the list
834     * when the iterator was constructed. No synchronization is
835     * needed while traversing the iterator. The iterator does
836     * <em>NOT</em> support the <code>remove</code> method.
837     */
838     public Iterator<E> iterator() {
839     return new COWIterator<E>(array(), 0);
840     }
841    
842     /**
843     * Returns an Iterator of the elements in this List (in proper sequence).
844     * The iterator provides a snapshot of the state of the list
845     * when the iterator was constructed. No synchronization is
846     * needed while traversing the iterator. The iterator does
847     * <em>NOT</em> support the <code>remove</code>, <code>set</code>,
848     * or <code>add</code> methods.
849     *
850     */
851     public ListIterator<E> listIterator() {
852     return new COWIterator<E>(array(), 0);
853     }
854    
855     /**
856     * Returns a ListIterator of the elements in this List (in proper
857     * sequence), starting at the specified position in the List. The
858     * specified index indicates the first element that would be returned by
859     * an initial call to nextElement. An initial call to previousElement
860     * would return the element with the specified index minus one.
861     * The ListIterator returned by this implementation will throw
862     * an UnsupportedOperationException in its remove, set and
863     * add methods.
864     *
865     * @param index index of first element to be returned from the
866     * ListIterator (by a call to getNext).
867 dl 1.6 * @throws IndexOutOfBoundsException index is out of range
868 tim 1.1 * (index &lt; 0 || index &gt; size()).
869     */
870     public ListIterator<E> listIterator(final int index) {
871     E[] elementData = array();
872     int len = elementData.length;
873     if (index<0 || index>len)
874     throw new IndexOutOfBoundsException("Index: "+index);
875    
876     return new COWIterator<E>(array(), index);
877     }
878    
879     private static class COWIterator<E> implements ListIterator<E> {
880    
881     /** Snapshot of the array **/
882     private final E[] array;
883    
884     /**
885     * Index of element to be returned by subsequent call to next.
886     */
887     private int cursor;
888    
889     private COWIterator(E[] elementArray, int initialCursor) {
890     array = elementArray;
891     cursor = initialCursor;
892     }
893    
894     public boolean hasNext() {
895     return cursor < array.length;
896     }
897    
898     public boolean hasPrevious() {
899     return cursor > 0;
900     }
901    
902     public E next() {
903     try {
904     return array[cursor++];
905 tim 1.10 } catch (IndexOutOfBoundsException ex) {
906 tim 1.1 throw new NoSuchElementException();
907     }
908     }
909    
910     public E previous() {
911     try {
912     return array[--cursor];
913     } catch(IndexOutOfBoundsException e) {
914     throw new NoSuchElementException();
915     }
916     }
917    
918     public int nextIndex() {
919     return cursor;
920     }
921    
922     public int previousIndex() {
923     return cursor-1;
924     }
925    
926     /**
927     * Not supported. Always throws UnsupportedOperationException.
928 dl 1.6 * @throws UnsupportedOperationException remove is not supported
929 tim 1.1 * by this Iterator.
930     */
931    
932     public void remove() {
933     throw new UnsupportedOperationException();
934     }
935    
936     /**
937     * Not supported. Always throws UnsupportedOperationException.
938 dl 1.6 * @throws UnsupportedOperationException set is not supported
939 tim 1.1 * by this Iterator.
940     */
941     public void set(E o) {
942     throw new UnsupportedOperationException();
943     }
944    
945     /**
946     * Not supported. Always throws UnsupportedOperationException.
947 dl 1.6 * @throws UnsupportedOperationException add is not supported
948 tim 1.1 * by this Iterator.
949     */
950     public void add(E o) {
951     throw new UnsupportedOperationException();
952     }
953     }
954    
955    
956     /**
957     * Returns a view of the portion of this List between fromIndex,
958     * inclusive, and toIndex, exclusive. The returned List is backed by this
959     * List, so changes in the returned List are reflected in this List, and
960     * vice-versa. While mutative operations are supported, they are
961     * probably not very useful for CopyOnWriteArrays.
962 tim 1.9 * <p>
963 tim 1.1 * The semantics of the List returned by this method become undefined if
964     * the backing list (i.e., this List) is <i>structurally modified</i> in
965     * any way other than via the returned List. (Structural modifications are
966     * those that change the size of the List, or otherwise perturb it in such
967     * a fashion that iterations in progress may yield incorrect results.)
968     *
969     * @param fromIndex low endpoint (inclusive) of the subList.
970 dl 1.6 * @param toIndex high endpoint (exclusive) of the subList.
971 tim 1.1 * @return a view of the specified range within this List.
972 dl 1.6 * @throws IndexOutOfBoundsException Illegal endpoint index value
973 tim 1.1 * (fromIndex &lt; 0 || toIndex &gt; size || fromIndex &gt; toIndex).
974     */
975     public synchronized List<E> subList(int fromIndex, int toIndex) {
976     // synchronized since sublist ctor depends on it.
977 dl 1.12 int len = array.length;
978 tim 1.1 if (fromIndex<0 || toIndex>len || fromIndex>toIndex)
979     throw new IndexOutOfBoundsException();
980     return new COWSubList<E>(this, fromIndex, toIndex);
981     }
982    
983     private static class COWSubList<E> extends AbstractList<E> {
984    
985     /*
986 dl 1.2 This class extends AbstractList merely for convenience, to
987     avoid having to define addAll, etc. This doesn't hurt, but
988     is wasteful. This class does not need or use modCount
989     mechanics in AbstractList, but does need to check for
990     concurrent modification using similar mechanics. On each
991     operation, the array that we expect the backing list to use
992     is checked and updated. Since we do this for all of the
993     base operations invoked by those defined in AbstractList,
994     all is well. While inefficient, this is not worth
995     improving. The kinds of list operations inherited from
996     AbstractList are are already so slow on COW sublists that
997     adding a bit more space/time doesn't seem even noticeable.
998 tim 1.1 */
999    
1000     private final CopyOnWriteArrayList<E> l;
1001     private final int offset;
1002     private int size;
1003     private E[] expectedArray;
1004    
1005     private COWSubList(CopyOnWriteArrayList<E> list,
1006     int fromIndex, int toIndex) {
1007     l = list;
1008     expectedArray = l.array();
1009     offset = fromIndex;
1010     size = toIndex - fromIndex;
1011     }
1012    
1013     // only call this holding l's lock
1014     private void checkForComodification() {
1015 dl 1.12 if (l.array != expectedArray)
1016 tim 1.1 throw new ConcurrentModificationException();
1017     }
1018    
1019     // only call this holding l's lock
1020     private void rangeCheck(int index) {
1021     if (index<0 || index>=size)
1022     throw new IndexOutOfBoundsException("Index: "+index+ ",Size: "+size);
1023     }
1024    
1025    
1026     public E set(int index, E element) {
1027     synchronized(l) {
1028     rangeCheck(index);
1029     checkForComodification();
1030     E x = l.set(index+offset, element);
1031 dl 1.12 expectedArray = l.array;
1032 tim 1.1 return x;
1033     }
1034     }
1035    
1036     public E get(int index) {
1037     synchronized(l) {
1038     rangeCheck(index);
1039     checkForComodification();
1040     return l.get(index+offset);
1041     }
1042     }
1043    
1044     public int size() {
1045     synchronized(l) {
1046     checkForComodification();
1047     return size;
1048     }
1049     }
1050    
1051     public void add(int index, E element) {
1052     synchronized(l) {
1053     checkForComodification();
1054     if (index<0 || index>size)
1055     throw new IndexOutOfBoundsException();
1056     l.add(index+offset, element);
1057 dl 1.12 expectedArray = l.array;
1058 tim 1.1 size++;
1059     }
1060     }
1061    
1062     public E remove(int index) {
1063     synchronized(l) {
1064     rangeCheck(index);
1065     checkForComodification();
1066     E result = l.remove(index+offset);
1067 dl 1.12 expectedArray = l.array;
1068 tim 1.1 size--;
1069     return result;
1070     }
1071     }
1072    
1073     public Iterator<E> iterator() {
1074     synchronized(l) {
1075     checkForComodification();
1076 tim 1.8 return new COWSubListIterator<E>(l, 0, offset, size);
1077 tim 1.1 }
1078     }
1079    
1080     public ListIterator<E> listIterator(final int index) {
1081     synchronized(l) {
1082     checkForComodification();
1083     if (index<0 || index>size)
1084     throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
1085 tim 1.8 return new COWSubListIterator<E>(l, index, offset, size);
1086 tim 1.1 }
1087     }
1088    
1089 tim 1.7 public List<E> subList(int fromIndex, int toIndex) {
1090     synchronized(l) {
1091     checkForComodification();
1092     if (fromIndex<0 || toIndex>size)
1093     throw new IndexOutOfBoundsException();
1094     return new COWSubList<E>(l, fromIndex+offset, toIndex+offset);
1095 tim 1.1 }
1096 tim 1.7 }
1097 tim 1.1
1098 tim 1.7 }
1099 tim 1.1
1100    
1101 tim 1.7 private static class COWSubListIterator<E> implements ListIterator<E> {
1102     private final ListIterator<E> i;
1103     private final int index;
1104     private final int offset;
1105     private final int size;
1106     private COWSubListIterator(List<E> l, int index, int offset, int size) {
1107     this.index = index;
1108     this.offset = offset;
1109     this.size = size;
1110     i = l.listIterator(index+offset);
1111     }
1112 tim 1.1
1113 tim 1.7 public boolean hasNext() {
1114     return nextIndex() < size;
1115     }
1116 tim 1.1
1117 tim 1.7 public E next() {
1118     if (hasNext())
1119     return i.next();
1120     else
1121     throw new NoSuchElementException();
1122     }
1123 tim 1.1
1124 tim 1.7 public boolean hasPrevious() {
1125     return previousIndex() >= 0;
1126     }
1127 tim 1.1
1128 tim 1.7 public E previous() {
1129     if (hasPrevious())
1130     return i.previous();
1131     else
1132     throw new NoSuchElementException();
1133     }
1134 tim 1.1
1135 tim 1.7 public int nextIndex() {
1136     return i.nextIndex() - offset;
1137     }
1138 tim 1.1
1139 tim 1.7 public int previousIndex() {
1140     return i.previousIndex() - offset;
1141 tim 1.1 }
1142    
1143 tim 1.7 public void remove() {
1144     throw new UnsupportedOperationException();
1145     }
1146 tim 1.1
1147 tim 1.7 public void set(E o) {
1148     throw new UnsupportedOperationException();
1149 tim 1.1 }
1150    
1151 tim 1.7 public void add(E o) {
1152     throw new UnsupportedOperationException();
1153     }
1154 tim 1.1 }
1155    
1156     }