History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/util/concurrent/CopyOnWriteArrayList.java (1 of 18352 files). Show all

Unified · Split

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