1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package java.util.concurrent;
18 
19 import java.io.IOException;
20 import java.io.ObjectInputStream;
21 import java.io.ObjectOutputStream;
22 import java.io.Serializable;
23 import java.util.AbstractList;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.Comparator;
27 import java.util.ConcurrentModificationException;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.ListIterator;
31 import java.util.NoSuchElementException;
32 import java.util.RandomAccess;
33 import java.util.function.Consumer;
34 import java.util.function.UnaryOperator;
35 
36 import libcore.util.EmptyArray;
37 import libcore.util.Objects;
38 
39 /**
40  * A thread-safe random-access list.
41  *
42  * <p>Read operations (including {@link #get}) do not block and may overlap with
43  * update operations. Reads reflect the results of the most recently completed
44  * operations. Aggregate operations like {@link #addAll} and {@link #clear} are
45  * atomic; they never expose an intermediate state.
46  *
47  * <p>Iterators of this list never throw {@link
48  * ConcurrentModificationException}. When an iterator is created, it keeps a
49  * copy of the list's contents. It is always safe to iterate this list, but
50  * iterations may not reflect the latest state of the list.
51  *
52  * <p>Iterators returned by this list and its sub lists cannot modify the
53  * underlying list. In particular, {@link Iterator#remove}, {@link
54  * ListIterator#add} and {@link ListIterator#set} all throw {@link
55  * UnsupportedOperationException}.
56  *
57  * <p>This class offers extended API beyond the {@link List} interface. It
58  * includes additional overloads for indexed search ({@link #indexOf} and {@link
59  * #lastIndexOf}) and methods for conditional adds ({@link #addIfAbsent} and
60  * {@link #addAllAbsent}).
61  */
62 public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, Serializable {
63 
64     private static final long serialVersionUID = 8673264195747942595L;
65 
66     /**
67      * Holds the latest snapshot of the list's data. This field is volatile so
68      * that data can be read without synchronization. As a consequence, all
69      * writes to this field must be atomic; it is an error to modify the
70      * contents of an array after it has been assigned to this field.
71      *
72      * Synchronization is required by all update operations. This defends
73      * against one update clobbering the result of another operation. For
74      * example, 100 threads simultaneously calling add() will grow the list's
75      * size by 100 when they have completed. No update operations are lost!
76      *
77      * Maintainers should be careful to read this field only once in
78      * non-blocking read methods. Write methods must be synchronized to avoid
79      * clobbering concurrent writes.
80      */
81     private transient volatile Object[] elements;
82 
83     /**
84      * Creates a new empty instance.
85      */
CopyOnWriteArrayList()86     public CopyOnWriteArrayList() {
87         elements = EmptyArray.OBJECT;
88     }
89 
90     /**
91      * Creates a new instance containing the elements of {@code collection}.
92      */
93     @SuppressWarnings("unchecked")
CopyOnWriteArrayList(Collection<? extends E> collection)94     public CopyOnWriteArrayList(Collection<? extends E> collection) {
95         this((E[]) collection.toArray());
96     }
97 
98     /**
99      * Creates a new instance containing the elements of {@code array}.
100      */
CopyOnWriteArrayList(E[] array)101     public CopyOnWriteArrayList(E[] array) {
102         this.elements = Arrays.copyOf(array, array.length, Object[].class);
103     }
104 
clone()105     @Override public Object clone() {
106         try {
107             CopyOnWriteArrayList result = (CopyOnWriteArrayList) super.clone();
108             result.elements = result.elements.clone();
109             return result;
110         } catch (CloneNotSupportedException e) {
111             throw new AssertionError(e);
112         }
113     }
114 
size()115     public int size() {
116         return elements.length;
117     }
118 
119     @SuppressWarnings("unchecked")
get(int index)120     public E get(int index) {
121         return (E) elements[index];
122     }
123 
contains(Object o)124     public boolean contains(Object o) {
125         return indexOf(o) != -1;
126     }
127 
containsAll(Collection<?> collection)128     public boolean containsAll(Collection<?> collection) {
129         Object[] snapshot = elements;
130         return containsAll(collection, snapshot, 0, snapshot.length);
131     }
132 
containsAll(Collection<?> collection, Object[] snapshot, int from, int to)133     static boolean containsAll(Collection<?> collection, Object[] snapshot, int from, int to) {
134         for (Object o : collection) {
135             if (indexOf(o, snapshot, from, to) == -1) {
136                 return false;
137             }
138         }
139         return true;
140     }
141 
142     /**
143      * Searches this list for {@code object} and returns the index of the first
144      * occurrence that is at or after {@code from}.
145      *
146      * @return the index or -1 if the object was not found.
147      */
indexOf(E object, int from)148     public int indexOf(E object, int from) {
149         Object[] snapshot = elements;
150         return indexOf(object, snapshot, from, snapshot.length);
151     }
152 
indexOf(Object object)153     public int indexOf(Object object) {
154         Object[] snapshot = elements;
155         return indexOf(object, snapshot, 0, snapshot.length);
156     }
157 
158     /**
159      * Searches this list for {@code object} and returns the index of the last
160      * occurrence that is before {@code to}.
161      *
162      * @return the index or -1 if the object was not found.
163      */
lastIndexOf(E object, int to)164     public int lastIndexOf(E object, int to) {
165         Object[] snapshot = elements;
166         return lastIndexOf(object, snapshot, 0, to);
167     }
168 
lastIndexOf(Object object)169     public int lastIndexOf(Object object) {
170         Object[] snapshot = elements;
171         return lastIndexOf(object, snapshot, 0, snapshot.length);
172     }
173 
isEmpty()174     public boolean isEmpty() {
175         return elements.length == 0;
176     }
177 
178     /**
179      * Returns an {@link Iterator} that iterates over the elements of this list
180      * as they were at the time of this method call. Changes to the list made
181      * after this method call will not be reflected by the iterator, nor will
182      * they trigger a {@link ConcurrentModificationException}.
183      *
184      * <p>The returned iterator does not support {@link Iterator#remove()}.
185      */
iterator()186     public Iterator<E> iterator() {
187         Object[] snapshot = elements;
188         return new CowIterator<E>(snapshot, 0, snapshot.length);
189     }
190 
191     /**
192      * Returns a {@link ListIterator} that iterates over the elements of this
193      * list as they were at the time of this method call. Changes to the list
194      * made after this method call will not be reflected by the iterator, nor
195      * will they trigger a {@link ConcurrentModificationException}.
196      *
197      * <p>The returned iterator does not support {@link ListIterator#add},
198      * {@link ListIterator#set} or {@link Iterator#remove()},
199      */
listIterator(int index)200     public ListIterator<E> listIterator(int index) {
201         Object[] snapshot = elements;
202         if (index < 0 || index > snapshot.length) {
203             throw new IndexOutOfBoundsException("index=" + index + ", length=" + snapshot.length);
204         }
205         CowIterator<E> result = new CowIterator<E>(snapshot, 0, snapshot.length);
206         result.index = index;
207         return result;
208     }
209 
210     /**
211      * Equivalent to {@code listIterator(0)}.
212      */
listIterator()213     public ListIterator<E> listIterator() {
214         Object[] snapshot = elements;
215         return new CowIterator<E>(snapshot, 0, snapshot.length);
216     }
217 
subList(int from, int to)218     public List<E> subList(int from, int to) {
219         Object[] snapshot = elements;
220         if (from < 0 || from > to || to > snapshot.length) {
221             throw new IndexOutOfBoundsException("from=" + from + ", to=" + to +
222                     ", list size=" + snapshot.length);
223         }
224         return new CowSubList(snapshot, from, to);
225     }
226 
toArray()227     public Object[] toArray() {
228         return elements.clone();
229     }
230 
231     @SuppressWarnings({"unchecked","SuspiciousSystemArraycopy"})
toArray(T[] contents)232     public <T> T[] toArray(T[] contents) {
233         Object[] snapshot = elements;
234         if (snapshot.length > contents.length) {
235             return (T[]) Arrays.copyOf(snapshot, snapshot.length, contents.getClass());
236         }
237         System.arraycopy(snapshot, 0, contents, 0, snapshot.length);
238         if (snapshot.length < contents.length) {
239             contents[snapshot.length] = null;
240         }
241         return contents;
242     }
243 
equals(Object other)244     @Override public boolean equals(Object other) {
245         if (other instanceof CopyOnWriteArrayList) {
246             return this == other
247                     || Arrays.equals(elements, ((CopyOnWriteArrayList<?>) other).elements);
248         } else if (other instanceof List) {
249             Object[] snapshot = elements;
250             Iterator<?> i = ((List<?>) other).iterator();
251             for (Object o : snapshot) {
252                 if (!i.hasNext() || !Objects.equal(o, i.next())) {
253                     return false;
254                 }
255             }
256             return !i.hasNext();
257         } else {
258             return false;
259         }
260     }
261 
hashCode()262     @Override public int hashCode() {
263         return Arrays.hashCode(elements);
264     }
265 
toString()266     @Override public String toString() {
267         return Arrays.toString(elements);
268     }
269 
add(E e)270     public synchronized boolean add(E e) {
271         Object[] newElements = new Object[elements.length + 1];
272         System.arraycopy(elements, 0, newElements, 0, elements.length);
273         newElements[elements.length] = e;
274         elements = newElements;
275         return true;
276     }
277 
add(int index, E e)278     public synchronized void add(int index, E e) {
279         Object[] newElements = new Object[elements.length + 1];
280         System.arraycopy(elements, 0, newElements, 0, index);
281         newElements[index] = e;
282         System.arraycopy(elements, index, newElements, index + 1, elements.length - index);
283         elements = newElements;
284     }
285 
addAll(Collection<? extends E> collection)286     public synchronized boolean addAll(Collection<? extends E> collection) {
287         return addAll(elements.length, collection);
288     }
289 
addAll(int index, Collection<? extends E> collection)290     public synchronized boolean addAll(int index, Collection<? extends E> collection) {
291         Object[] toAdd = collection.toArray();
292         Object[] newElements = new Object[elements.length + toAdd.length];
293         System.arraycopy(elements, 0, newElements, 0, index);
294         System.arraycopy(toAdd, 0, newElements, index, toAdd.length);
295         System.arraycopy(elements, index,
296                 newElements, index + toAdd.length, elements.length - index);
297         elements = newElements;
298         return toAdd.length > 0;
299     }
300 
301     /**
302      * Adds the elements of {@code collection} that are not already present in
303      * this list. If {@code collection} includes a repeated value, at most one
304      * occurrence of that value will be added to this list. Elements are added
305      * at the end of this list.
306      *
307      * <p>Callers of this method may prefer {@link CopyOnWriteArraySet}, whose
308      * API is more appropriate for set operations.
309      */
addAllAbsent(Collection<? extends E> collection)310     public synchronized int addAllAbsent(Collection<? extends E> collection) {
311         Object[] toAdd = collection.toArray();
312         Object[] newElements = new Object[elements.length + toAdd.length];
313         System.arraycopy(elements, 0, newElements, 0, elements.length);
314         int addedCount = 0;
315         for (Object o : toAdd) {
316             if (indexOf(o, newElements, 0, elements.length + addedCount) == -1) {
317                 newElements[elements.length + addedCount++] = o;
318             }
319         }
320         if (addedCount < toAdd.length) {
321             newElements = Arrays.copyOfRange(
322                     newElements, 0, elements.length + addedCount); // trim to size
323         }
324         elements = newElements;
325         return addedCount;
326     }
327 
328     /**
329      * Adds {@code object} to the end of this list if it is not already present.
330      *
331      * <p>Callers of this method may prefer {@link CopyOnWriteArraySet}, whose
332      * API is more appropriate for set operations.
333      */
addIfAbsent(E object)334     public synchronized boolean addIfAbsent(E object) {
335         if (contains(object)) {
336             return false;
337         }
338         add(object);
339         return true;
340     }
341 
clear()342     @Override public synchronized void clear() {
343         elements = EmptyArray.OBJECT;
344     }
345 
remove(int index)346     public synchronized E remove(int index) {
347         @SuppressWarnings("unchecked")
348         E removed = (E) elements[index];
349         removeRange(index, index + 1);
350         return removed;
351     }
352 
remove(Object o)353     public synchronized boolean remove(Object o) {
354         int index = indexOf(o);
355         if (index == -1) {
356             return false;
357         }
358         remove(index);
359         return true;
360     }
361 
removeAll(Collection<?> collection)362     public synchronized boolean removeAll(Collection<?> collection) {
363         return removeOrRetain(collection, false, 0, elements.length) != 0;
364     }
365 
retainAll(Collection<?> collection)366     public synchronized boolean retainAll(Collection<?> collection) {
367         return removeOrRetain(collection, true, 0, elements.length) != 0;
368     }
369 
370     @Override
replaceAll(UnaryOperator<E> operator)371     public synchronized void replaceAll(UnaryOperator<E> operator) {
372         replaceInRange(0, elements.length,operator);
373     }
374 
replaceInRange(int from, int to, UnaryOperator<E> operator)375     private void replaceInRange(int from, int to, UnaryOperator<E> operator) {
376         java.util.Objects.requireNonNull(operator);
377         Object[] newElements = new Object[elements.length];
378         System.arraycopy(elements, 0, newElements, 0, newElements.length);
379         for (int i = from; i < to; i++) {
380             @SuppressWarnings("unchecked") E e = (E) elements[i];
381             newElements[i] = operator.apply(e);
382         }
383         elements = newElements;
384     }
385 
386     @Override
sort(Comparator<? super E> c)387     public synchronized void sort(Comparator<? super E> c) {
388         sortInRange(0, elements.length, c);
389     }
390 
sortInRange(int from, int to, Comparator<? super E> c)391     private synchronized void sortInRange(int from, int to, Comparator<? super E> c) {
392         java.util.Objects.requireNonNull(c);
393         Object[] newElements = new Object[elements.length];
394         System.arraycopy(elements, 0, newElements, 0, newElements.length);
395         Arrays.sort((E[])newElements, from, to, c);
396         elements = newElements;
397     }
398 
399     @Override
forEach(Consumer<? super E> action)400     public void forEach(Consumer<? super E> action) {
401         forInRange(0, elements.length, action);
402     }
403 
forInRange(int from, int to, Consumer<? super E> action)404     private void forInRange(int from, int to, Consumer<? super E> action) {
405         java.util.Objects.requireNonNull(action);
406         Object[] newElements = new Object[elements.length];
407         System.arraycopy(elements, 0, newElements, 0, newElements.length);
408         for (int i = from; i < to; i++) {
409             action.accept((E)newElements[i]);
410         }
411     }
412 
413     /**
414      * Removes or retains the elements in {@code collection}. Returns the number
415      * of elements removed.
416      */
removeOrRetain(Collection<?> collection, boolean retain, int from, int to)417     private int removeOrRetain(Collection<?> collection, boolean retain, int from, int to) {
418         for (int i = from; i < to; i++) {
419             if (collection.contains(elements[i]) == retain) {
420                 continue;
421             }
422 
423             /*
424              * We've encountered an element that must be removed! Create a new
425              * array and copy in the surviving elements one by one.
426              */
427             Object[] newElements = new Object[elements.length - 1];
428             System.arraycopy(elements, 0, newElements, 0, i);
429             int newSize = i;
430             for (int j = i + 1; j < to; j++) {
431                 if (collection.contains(elements[j]) == retain) {
432                     newElements[newSize++] = elements[j];
433                 }
434             }
435 
436             /*
437              * Copy the elements after 'to'. This is only useful for sub lists,
438              * where 'to' will be less than elements.length.
439              */
440             System.arraycopy(elements, to, newElements, newSize, elements.length - to);
441             newSize += (elements.length - to);
442 
443             if (newSize < newElements.length) {
444                 newElements = Arrays.copyOfRange(newElements, 0, newSize); // trim to size
445             }
446             int removed = elements.length - newElements.length;
447             elements = newElements;
448             return removed;
449         }
450 
451         // we made it all the way through the loop without making any changes
452         return 0;
453     }
454 
set(int index, E e)455     public synchronized E set(int index, E e) {
456         Object[] newElements = elements.clone();
457         @SuppressWarnings("unchecked")
458         E result = (E) newElements[index];
459         newElements[index] = e;
460         elements = newElements;
461         return result;
462     }
463 
removeRange(int from, int to)464     private void removeRange(int from, int to) {
465         Object[] newElements = new Object[elements.length - (to - from)];
466         System.arraycopy(elements, 0, newElements, 0, from);
467         System.arraycopy(elements, to, newElements, from, elements.length - to);
468         elements = newElements;
469     }
470 
lastIndexOf(Object o, Object[] data, int from, int to)471     static int lastIndexOf(Object o, Object[] data, int from, int to) {
472         if (o == null) {
473             for (int i = to - 1; i >= from; i--) {
474                 if (data[i] == null) {
475                     return i;
476                 }
477             }
478         } else {
479             for (int i = to - 1; i >= from; i--) {
480                 if (o.equals(data[i])) {
481                     return i;
482                 }
483             }
484         }
485         return -1;
486     }
487 
indexOf(Object o, Object[] data, int from, int to)488     static int indexOf(Object o, Object[] data, int from, int to) {
489         if (o == null) {
490             for (int i = from; i < to; i++) {
491                 if (data[i] == null) {
492                     return i;
493                 }
494             }
495         } else {
496             for (int i = from; i < to; i++) {
497                 if (o.equals(data[i])) {
498                     return i;
499                 }
500             }
501         }
502         return -1;
503     }
504 
getArray()505     final Object[] getArray() {
506         // CopyOnWriteArraySet needs this.
507         return elements;
508     }
509 
510     /**
511      * The sub list is thread safe and supports non-blocking reads. Doing so is
512      * more difficult than in the full list, because each read needs to examine
513      * four fields worth of state:
514      *  - the elements array of the full list
515      *  - two integers for the bounds of this sub list
516      *  - the expected elements array (to detect concurrent modification)
517      *
518      * This is accomplished by aggregating the sub list's three fields into a
519      * single snapshot object representing the current slice. This permits reads
520      * to be internally consistent without synchronization. This takes advantage
521      * of Java's concurrency semantics for final fields.
522      */
523     class CowSubList extends AbstractList<E> {
524 
525         /*
526          * An immutable snapshot of a sub list's state. By gathering all three
527          * of the sub list's fields in an immutable object,
528          */
529         private volatile Slice slice;
530 
CowSubList(Object[] expectedElements, int from, int to)531         public CowSubList(Object[] expectedElements, int from, int to) {
532             this.slice = new Slice(expectedElements, from, to);
533         }
534 
size()535         @Override public int size() {
536             Slice slice = this.slice;
537             return slice.to - slice.from;
538         }
539 
isEmpty()540         @Override public boolean isEmpty() {
541             Slice slice = this.slice;
542             return slice.from == slice.to;
543         }
544 
545         @SuppressWarnings("unchecked")
get(int index)546         @Override public E get(int index) {
547             Slice slice = this.slice;
548             Object[] snapshot = elements;
549             slice.checkElementIndex(index);
550             slice.checkConcurrentModification(snapshot);
551             return (E) snapshot[index + slice.from];
552         }
553 
iterator()554         @Override public Iterator<E> iterator() {
555             return listIterator(0);
556         }
557 
listIterator()558         @Override public ListIterator<E> listIterator() {
559             return listIterator(0);
560         }
561 
listIterator(int index)562         @Override public ListIterator<E> listIterator(int index) {
563             Slice slice = this.slice;
564             Object[] snapshot = elements;
565             slice.checkPositionIndex(index);
566             slice.checkConcurrentModification(snapshot);
567             CowIterator<E> result = new CowIterator<E>(snapshot, slice.from, slice.to);
568             result.index = slice.from + index;
569             return result;
570         }
571 
indexOf(Object object)572         @Override public int indexOf(Object object) {
573             Slice slice = this.slice;
574             Object[] snapshot = elements;
575             slice.checkConcurrentModification(snapshot);
576             int result = CopyOnWriteArrayList.indexOf(object, snapshot, slice.from, slice.to);
577             return (result != -1) ? (result - slice.from) : -1;
578         }
579 
lastIndexOf(Object object)580         @Override public int lastIndexOf(Object object) {
581             Slice slice = this.slice;
582             Object[] snapshot = elements;
583             slice.checkConcurrentModification(snapshot);
584             int result = CopyOnWriteArrayList.lastIndexOf(object, snapshot, slice.from, slice.to);
585             return (result != -1) ? (result - slice.from) : -1;
586         }
587 
contains(Object object)588         @Override public boolean contains(Object object) {
589             return indexOf(object) != -1;
590         }
591 
containsAll(Collection<?> collection)592         @Override public boolean containsAll(Collection<?> collection) {
593             Slice slice = this.slice;
594             Object[] snapshot = elements;
595             slice.checkConcurrentModification(snapshot);
596             return CopyOnWriteArrayList.containsAll(collection, snapshot, slice.from, slice.to);
597         }
598 
subList(int from, int to)599         @Override public List<E> subList(int from, int to) {
600             Slice slice = this.slice;
601             if (from < 0 || from > to || to > size()) {
602                 throw new IndexOutOfBoundsException("from=" + from + ", to=" + to +
603                         ", list size=" + size());
604             }
605             return new CowSubList(slice.expectedElements, slice.from + from, slice.from + to);
606         }
607 
remove(int index)608         @Override public E remove(int index) {
609             synchronized (CopyOnWriteArrayList.this) {
610                 slice.checkElementIndex(index);
611                 slice.checkConcurrentModification(elements);
612                 E removed = CopyOnWriteArrayList.this.remove(slice.from + index);
613                 slice = new Slice(elements, slice.from, slice.to - 1);
614                 return removed;
615             }
616         }
617 
clear()618         @Override public void clear() {
619             synchronized (CopyOnWriteArrayList.this) {
620                 slice.checkConcurrentModification(elements);
621                 CopyOnWriteArrayList.this.removeRange(slice.from, slice.to);
622                 slice = new Slice(elements, slice.from, slice.from);
623             }
624         }
625 
add(int index, E object)626         @Override public void add(int index, E object) {
627             synchronized (CopyOnWriteArrayList.this) {
628                 slice.checkPositionIndex(index);
629                 slice.checkConcurrentModification(elements);
630                 CopyOnWriteArrayList.this.add(index + slice.from, object);
631                 slice = new Slice(elements, slice.from, slice.to + 1);
632             }
633         }
634 
add(E object)635         @Override public boolean add(E object) {
636             synchronized (CopyOnWriteArrayList.this) {
637                 add(slice.to - slice.from, object);
638                 return true;
639             }
640         }
641 
addAll(int index, Collection<? extends E> collection)642         @Override public boolean addAll(int index, Collection<? extends E> collection) {
643             synchronized (CopyOnWriteArrayList.this) {
644                 slice.checkPositionIndex(index);
645                 slice.checkConcurrentModification(elements);
646                 int oldSize = elements.length;
647                 boolean result = CopyOnWriteArrayList.this.addAll(index + slice.from, collection);
648                 slice = new Slice(elements, slice.from, slice.to + (elements.length - oldSize));
649                 return result;
650             }
651         }
652 
addAll(Collection<? extends E> collection)653         @Override public boolean addAll(Collection<? extends E> collection) {
654             synchronized (CopyOnWriteArrayList.this) {
655                 return addAll(size(), collection);
656             }
657         }
658 
set(int index, E object)659         @Override public E set(int index, E object) {
660             synchronized (CopyOnWriteArrayList.this) {
661                 slice.checkElementIndex(index);
662                 slice.checkConcurrentModification(elements);
663                 E result = CopyOnWriteArrayList.this.set(index + slice.from, object);
664                 slice = new Slice(elements, slice.from, slice.to);
665                 return result;
666             }
667         }
668 
remove(Object object)669         @Override public boolean remove(Object object) {
670             synchronized (CopyOnWriteArrayList.this) {
671                 int index = indexOf(object);
672                 if (index == -1) {
673                     return false;
674                 }
675                 remove(index);
676                 return true;
677             }
678         }
679 
removeAll(Collection<?> collection)680         @Override public boolean removeAll(Collection<?> collection) {
681             synchronized (CopyOnWriteArrayList.this) {
682                 slice.checkConcurrentModification(elements);
683                 int removed = removeOrRetain(collection, false, slice.from, slice.to);
684                 slice = new Slice(elements, slice.from, slice.to - removed);
685                 return removed != 0;
686             }
687         }
688 
retainAll(Collection<?> collection)689         @Override public boolean retainAll(Collection<?> collection) {
690             synchronized (CopyOnWriteArrayList.this) {
691                 slice.checkConcurrentModification(elements);
692                 int removed = removeOrRetain(collection, true, slice.from, slice.to);
693                 slice = new Slice(elements, slice.from, slice.to - removed);
694                 return removed != 0;
695             }
696         }
697 
698         @Override
forEach(Consumer<? super E> action)699         public void forEach(Consumer<? super E> action) {
700             CopyOnWriteArrayList.this.forInRange(slice.from, slice.to, action);
701         }
702 
703         @Override
replaceAll(UnaryOperator<E> operator)704         public void replaceAll(UnaryOperator<E> operator) {
705             synchronized (CopyOnWriteArrayList.this) {
706                 slice.checkConcurrentModification(elements);
707                 CopyOnWriteArrayList.this.replaceInRange(slice.from, slice.to, operator);
708                 slice = new Slice(elements, slice.from, slice.to);
709             }
710         }
711 
712         @Override
sort(Comparator<? super E> c)713         public synchronized void sort(Comparator<? super E> c) {
714             synchronized (CopyOnWriteArrayList.this) {
715                 slice.checkConcurrentModification(elements);
716                 CopyOnWriteArrayList.this.sortInRange(slice.from, slice.to, c);
717                 slice = new Slice(elements, slice.from, slice.to);
718             }
719         }
720     }
721 
722     static class Slice {
723         private final Object[] expectedElements;
724         private final int from;
725         private final int to;
726 
Slice(Object[] expectedElements, int from, int to)727         Slice(Object[] expectedElements, int from, int to) {
728             this.expectedElements = expectedElements;
729             this.from = from;
730             this.to = to;
731         }
732 
733         /**
734          * Throws if {@code index} doesn't identify an element in the array.
735          */
checkElementIndex(int index)736         void checkElementIndex(int index) {
737             if (index < 0 || index >= to - from) {
738                 throw new IndexOutOfBoundsException("index=" + index + ", size=" + (to - from));
739             }
740         }
741 
742         /**
743          * Throws if {@code index} doesn't identify an insertion point in the
744          * array. Unlike element index, it's okay to add or iterate at size().
745          */
checkPositionIndex(int index)746         void checkPositionIndex(int index) {
747             if (index < 0 || index > to - from) {
748                 throw new IndexOutOfBoundsException("index=" + index + ", size=" + (to - from));
749             }
750         }
751 
checkConcurrentModification(Object[] snapshot)752         void checkConcurrentModification(Object[] snapshot) {
753             if (expectedElements != snapshot) {
754                 throw new ConcurrentModificationException();
755             }
756         }
757     }
758 
759     /**
760      * Iterates an immutable snapshot of the list.
761      */
762     static class CowIterator<E> implements ListIterator<E> {
763         private final Object[] snapshot;
764         private final int from;
765         private final int to;
766         private int index = 0;
767 
CowIterator(Object[] snapshot, int from, int to)768         CowIterator(Object[] snapshot, int from, int to) {
769             this.snapshot = snapshot;
770             this.from = from;
771             this.to = to;
772             this.index = from;
773         }
774 
add(E object)775         public void add(E object) {
776             throw new UnsupportedOperationException();
777         }
778 
hasNext()779         public boolean hasNext() {
780             return index < to;
781         }
782 
hasPrevious()783         public boolean hasPrevious() {
784             return index > from;
785         }
786 
787         @SuppressWarnings("unchecked")
next()788         public E next() {
789             if (index < to) {
790                 return (E) snapshot[index++];
791             } else {
792                 throw new NoSuchElementException();
793             }
794         }
795 
nextIndex()796         public int nextIndex() {
797             return index;
798         }
799 
800         @SuppressWarnings("unchecked")
previous()801         public E previous() {
802             if (index > from) {
803                 return (E) snapshot[--index];
804             } else {
805                 throw new NoSuchElementException();
806             }
807         }
808 
previousIndex()809         public int previousIndex() {
810             return index - 1;
811         }
812 
remove()813         public void remove() {
814             throw new UnsupportedOperationException();
815         }
816 
set(E object)817         public void set(E object) {
818             throw new UnsupportedOperationException();
819         }
820 
821         @Override
forEachRemaining(Consumer<? super E> action)822         public void forEachRemaining(Consumer<? super E> action) {
823             java.util.Objects.requireNonNull(action);
824             Object[] elements = snapshot;
825             for (int i = index; i < to; i++) {
826                 @SuppressWarnings("unchecked") E e = (E) elements[i];
827                 action.accept(e);
828             }
829             index = to;
830         }
831     }
832 
writeObject(ObjectOutputStream out)833     private void writeObject(ObjectOutputStream out) throws IOException {
834         Object[] snapshot = elements;
835         out.defaultWriteObject();
836         out.writeInt(snapshot.length);
837         for (Object o : snapshot) {
838             out.writeObject(o);
839         }
840     }
841 
readObject(ObjectInputStream in)842     private synchronized void readObject(ObjectInputStream in)
843             throws IOException, ClassNotFoundException {
844         in.defaultReadObject();
845         Object[] snapshot = new Object[in.readInt()];
846         for (int i = 0; i < snapshot.length; i++) {
847             snapshot[i] = in.readObject();
848         }
849         elements = snapshot;
850     }
851 }
852