ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.35
Committed: Sun Jan 18 20:17:33 2015 UTC (9 years, 4 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.34: +1 -0 lines
Log Message:
exactly one blank line before and after package statements

File Contents

# User Rev Content
1 dl 1.1 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3     * Expert Group and released to the public domain, as explained at
4     * http://creativecommons.org/publicdomain/zero/1.0/
5     */
6    
7     package jsr166e.extra;
8 jsr166 1.35
9 dl 1.28 import jsr166e.StampedLock;
10 dl 1.1 import java.util.*;
11    
12     /**
13 dl 1.2 * A class with the same methods and array-based characteristics as
14     * {@link java.util.Vector} but with reduced contention and improved
15 dl 1.1 * throughput when invocations of read-only methods by multiple
16 jsr166 1.3 * threads are most common.
17 dl 1.1 *
18 jsr166 1.31 * <p>The iterators returned by this class's {@link #iterator()
19 dl 1.1 * iterator} and {@link #listIterator(int) listIterator} methods are
20     * best-effort in the presence of concurrent modifications, and do
21     * <em>NOT</em> throw {@link ConcurrentModificationException}. An
22     * iterator's {@code next()} method returns consecutive elements as
23 jsr166 1.13 * they appear in the underlying array upon each access. Alternatively,
24 dl 1.5 * method {@link #snapshotIterator} may be used for deterministic
25     * traversals, at the expense of making a copy, and unavailability of
26     * method {@code Iterator.remove}.
27 dl 1.1 *
28     * <p>Otherwise, this class supports all methods, under the same
29     * documented specifications, as {@code Vector}. Consult {@link
30     * java.util.Vector} for detailed specifications. Additionally, this
31     * class provides methods {@link #addIfAbsent} and {@link
32     * #addAllAbsent}.
33     *
34     * @author Doug Lea
35     */
36 jsr166 1.14 public class ReadMostlyVector<E>
37     implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
38 dl 1.1 private static final long serialVersionUID = 8673264195747942595L;
39    
40     /*
41     * This class exists mainly as a vehicle to exercise various
42 dl 1.2 * constructions using SequenceLocks. Read-only methods
43     * take one of a few forms:
44     *
45     * Short methods,including get(index), continually retry obtaining
46     * a snapshot of array, count, and element, using sequence number
47     * to validate.
48 jsr166 1.3 *
49 dl 1.2 * Methods that are potentially O(n) (or worse) try once in
50     * read-only mode, and then lock. When in read-only mode, they
51     * validate only at the end of an array scan unless the element is
52     * actually used (for example, as an argument of method equals).
53 jsr166 1.21 *
54     * We rely on some invariants that are always true, even for field
55     * reads in read-only mode that have not yet been validated:
56     * - array != null
57     * - count >= 0
58 dl 1.1 */
59    
60     /**
61     * The maximum size of array to allocate.
62     * See CopyOnWriteArrayList for explanation.
63     */
64     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
65    
66 jsr166 1.24 // fields are non-private to simplify nested class access
67 dl 1.28 Object[] array;
68     final StampedLock lock;
69     int count;
70 dl 1.1 final int capacityIncrement;
71    
72     /**
73     * Creates an empty vector with the given initial capacity and
74     * capacity increment.
75     *
76     * @param initialCapacity the initial capacity of the underlying array
77     * @param capacityIncrement if non-zero, the number to
78     * add when resizing to accommodate additional elements.
79     * If zero, the array size is doubled when resized.
80     *
81     * @throws IllegalArgumentException if initial capacity is negative
82     */
83     public ReadMostlyVector(int initialCapacity, int capacityIncrement) {
84     super();
85     if (initialCapacity < 0)
86     throw new IllegalArgumentException("Illegal Capacity: "+
87     initialCapacity);
88     this.array = new Object[initialCapacity];
89     this.capacityIncrement = capacityIncrement;
90 dl 1.28 this.lock = new StampedLock();
91 dl 1.1 }
92    
93     /**
94     * Creates an empty vector with the given initial capacity.
95     *
96     * @param initialCapacity the initial capacity of the underlying array
97     * @throws IllegalArgumentException if initial capacity is negative
98     */
99     public ReadMostlyVector(int initialCapacity) {
100     this(initialCapacity, 0);
101     }
102    
103     /**
104 dl 1.28 * Creates an empty vector.
105 dl 1.1 */
106     public ReadMostlyVector() {
107 dl 1.28 this.capacityIncrement = 0;
108     this.lock = new StampedLock();
109 dl 1.1 }
110    
111     /**
112     * Creates a vector containing the elements of the specified
113     * collection, in the order they are returned by the collection's
114     * iterator.
115     *
116     * @param c the collection of initially held elements
117     * @throws NullPointerException if the specified collection is null
118     */
119     public ReadMostlyVector(Collection<? extends E> c) {
120     Object[] elements = c.toArray();
121     // c.toArray might (incorrectly) not return Object[] (see 6260652)
122     if (elements.getClass() != Object[].class)
123     elements = Arrays.copyOf(elements, elements.length, Object[].class);
124     this.array = elements;
125     this.count = elements.length;
126     this.capacityIncrement = 0;
127 dl 1.28 this.lock = new StampedLock();
128 dl 1.1 }
129    
130     // internal constructor for clone
131     ReadMostlyVector(Object[] array, int count, int capacityIncrement) {
132     this.array = array;
133     this.count = count;
134     this.capacityIncrement = capacityIncrement;
135 dl 1.28 this.lock = new StampedLock();
136 dl 1.1 }
137    
138 dl 1.28 static final int INITIAL_CAP = 16;
139    
140 dl 1.1 // For explanation, see CopyOnWriteArrayList
141 dl 1.12 final Object[] grow(int minCapacity) {
142 dl 1.28 Object[] items;
143     int newCapacity;
144     if ((items = array) == null)
145     newCapacity = INITIAL_CAP;
146     else {
147     int oldCapacity = array.length;
148     newCapacity = oldCapacity + ((capacityIncrement > 0) ?
149 dl 1.1 capacityIncrement : oldCapacity);
150 dl 1.28 }
151 dl 1.1 if (newCapacity - minCapacity < 0)
152     newCapacity = minCapacity;
153 dl 1.28 if (newCapacity - MAX_ARRAY_SIZE > 0) {
154     if (minCapacity < 0) // overflow
155     throw new OutOfMemoryError();
156     else if (minCapacity > MAX_ARRAY_SIZE)
157     newCapacity = Integer.MAX_VALUE;
158     else
159     newCapacity = MAX_ARRAY_SIZE;
160     }
161 jsr166 1.29 return array = ((items == null) ?
162 dl 1.28 new Object[newCapacity] :
163     Arrays.copyOf(items, newCapacity));
164 dl 1.1 }
165    
166     /*
167     * Internal versions of most base functionality, wrapped
168     * in different ways from public methods from this class
169     * as well as sublist and iterator classes.
170     */
171    
172 dl 1.28 static int findFirstIndex(Object[] items, Object x, int index, int fence) {
173     int len;
174     if (items != null && (len = items.length) > 0) {
175 jsr166 1.30 int start = (index < 0) ? 0 : index;
176 dl 1.28 int bound = (fence < len) ? fence : len;
177     for (int i = start; i < bound; ++i) {
178     Object e = items[i];
179     if ((x == null) ? e == null : x.equals(e))
180     return i;
181     }
182 dl 1.2 }
183     return -1;
184     }
185    
186 dl 1.28 static int findLastIndex(Object[] items, Object x, int index, int origin) {
187     int len;
188     if (items != null && (len = items.length) > 0) {
189     int last = (index < len) ? index : len - 1;
190     int start = (origin < 0) ? 0 : origin;
191     for (int i = last; i >= start; --i) {
192     Object e = items[i];
193     if ((x == null) ? e == null : x.equals(e))
194     return i;
195     }
196 dl 1.2 }
197     return -1;
198     }
199    
200 jsr166 1.14 final void rawAdd(E e) {
201 dl 1.2 int n = count;
202 dl 1.11 Object[] items = array;
203 dl 1.28 if (items == null || n >= items.length)
204 dl 1.12 items = grow(n + 1);
205     items[n] = e;
206 dl 1.2 count = n + 1;
207 dl 1.1 }
208    
209 jsr166 1.14 final void rawAddAt(int index, E e) {
210 dl 1.2 int n = count;
211 dl 1.12 Object[] items = array;
212 dl 1.2 if (index > n)
213 dl 1.1 throw new ArrayIndexOutOfBoundsException(index);
214 dl 1.28 if (items == null || n >= items.length)
215 dl 1.12 items = grow(n + 1);
216 dl 1.2 if (index < n)
217 dl 1.11 System.arraycopy(items, index, items, index + 1, n - index);
218     items[index] = e;
219 dl 1.2 count = n + 1;
220 dl 1.1 }
221    
222 dl 1.4 final boolean rawAddAllAt(int index, Object[] elements) {
223 dl 1.2 int n = count;
224 dl 1.12 Object[] items = array;
225 dl 1.2 if (index < 0 || index > n)
226 dl 1.1 throw new ArrayIndexOutOfBoundsException(index);
227     int len = elements.length;
228     if (len == 0)
229     return false;
230 dl 1.2 int newCount = n + len;
231 dl 1.28 if (items == null || newCount >= items.length)
232 dl 1.12 items = grow(newCount);
233 dl 1.11 int mv = n - index;
234 dl 1.1 if (mv > 0)
235 dl 1.11 System.arraycopy(items, index, items, index + len, mv);
236     System.arraycopy(elements, 0, items, index, len);
237 dl 1.1 count = newCount;
238     return true;
239     }
240    
241 dl 1.4 final boolean rawRemoveAt(int index) {
242 dl 1.12 int n = count - 1;
243 dl 1.11 Object[] items = array;
244 dl 1.28 if (items == null || index < 0 || index > n)
245 dl 1.1 return false;
246 dl 1.2 int mv = n - index;
247 dl 1.1 if (mv > 0)
248 dl 1.11 System.arraycopy(items, index + 1, items, index, mv);
249     items[n] = null;
250 dl 1.2 count = n;
251 dl 1.1 return true;
252     }
253    
254     /**
255     * Internal version of removeAll for lists and sublists. In this
256 dl 1.2 * and other similar methods below, the bound argument is, if
257     * non-negative, the purported upper bound of a list/sublist, or
258     * is left negative if the bound should be determined via count
259     * field under lock.
260 dl 1.1 */
261 dl 1.28 final boolean lockedRemoveAll(Collection<?> c, int origin, int bound) {
262 dl 1.1 boolean removed = false;
263 dl 1.28 final StampedLock lock = this.lock;
264     long stamp = lock.writeLock();
265 dl 1.1 try {
266 dl 1.2 int n = count;
267     int fence = bound < 0 || bound > n ? n : bound;
268 dl 1.1 if (origin >= 0 && origin < fence) {
269     for (Object x : c) {
270 dl 1.28 while (rawRemoveAt(findFirstIndex(array, x, origin, fence)))
271 dl 1.1 removed = true;
272     }
273     }
274     } finally {
275 dl 1.28 lock.unlockWrite(stamp);
276 dl 1.1 }
277     return removed;
278     }
279    
280 dl 1.28 final boolean lockedRetainAll(Collection<?> c, int origin, int bound) {
281     final StampedLock lock = this.lock;
282 dl 1.1 boolean removed = false;
283     if (c != this) {
284 dl 1.28 long stamp = lock.writeLock();
285 dl 1.1 try {
286 dl 1.28 Object[] items;
287     int i, n;
288     if ((items = array) != null && (n = count) > 0 &&
289     n < items.length && (i = origin) >= 0) {
290     int fence = bound < 0 || bound > n ? n : bound;
291     while (i < fence) {
292     if (c.contains(items[i]))
293     ++i;
294     else {
295     --fence;
296     int mv = --n - i;
297     if (mv > 0)
298     System.arraycopy(items, i + 1, items, i, mv);
299     }
300     }
301     if (count != n) {
302     count = n;
303     removed = true;
304 dl 1.1 }
305     }
306     } finally {
307 dl 1.28 lock.unlockWrite(stamp);
308 dl 1.1 }
309     }
310     return removed;
311     }
312    
313 dl 1.2 final void internalClear(int origin, int bound) {
314 dl 1.28 Object[] items;
315     int n, len;
316     if ((items = array) != null && (len = items.length) > 0) {
317     if (origin < 0)
318     origin = 0;
319     if ((n = count) > len)
320     n = len;
321     int fence = bound < 0 || bound > n ? n : bound;
322 dl 1.1 int removed = fence - origin;
323 dl 1.2 int newCount = n - removed;
324     int mv = n - (origin + removed);
325 dl 1.1 if (mv > 0)
326 dl 1.11 System.arraycopy(items, origin + removed, items, origin, mv);
327 dl 1.2 for (int i = n; i < newCount; ++i)
328 dl 1.11 items[i] = null;
329 dl 1.1 count = newCount;
330     }
331     }
332    
333 dl 1.2 final boolean internalContainsAll(Collection<?> c, int origin, int bound) {
334 dl 1.28 Object[] items;
335     int n, len;
336     if ((items = array) != null && (len = items.length) > 0) {
337     if (origin < 0)
338     origin = 0;
339     if ((n = count) > len)
340     n = len;
341     int fence = bound < 0 || bound > n ? n : bound;
342     for (Object e : c) {
343     if (findFirstIndex(items, e, origin, fence) < 0)
344     return false;
345 dl 1.1 }
346     }
347 dl 1.28 else if (!c.isEmpty())
348     return false;
349     return true;
350 dl 1.1 }
351    
352 dl 1.2 final boolean internalEquals(List<?> list, int origin, int bound) {
353 dl 1.28 Object[] items;
354     int n, len;
355     if ((items = array) != null && (len = items.length) > 0) {
356     if (origin < 0)
357     origin = 0;
358     if ((n = count) > len)
359     n = len;
360     int fence = bound < 0 || bound > n ? n : bound;
361     Iterator<?> it = list.iterator();
362     for (int i = origin; i < fence; ++i) {
363     if (!it.hasNext())
364     return false;
365     Object y = it.next();
366     Object x = items[i];
367     if (x != y && (x == null || !x.equals(y)))
368     return false;
369 dl 1.1 }
370 dl 1.28 if (it.hasNext())
371     return false;
372 dl 1.1 }
373 dl 1.28 else if (!list.isEmpty())
374     return false;
375     return true;
376 dl 1.1 }
377    
378 dl 1.2 final int internalHashCode(int origin, int bound) {
379 dl 1.28 int hash = 1;
380     Object[] items;
381     int n, len;
382     if ((items = array) != null && (len = items.length) > 0) {
383     if (origin < 0)
384     origin = 0;
385     if ((n = count) > len)
386     n = len;
387     int fence = bound < 0 || bound > n ? n : bound;
388     for (int i = origin; i < fence; ++i) {
389     Object e = items[i];
390     hash = 31*hash + (e == null ? 0 : e.hashCode());
391 dl 1.1 }
392     }
393     return hash;
394     }
395    
396 dl 1.2 final String internalToString(int origin, int bound) {
397 dl 1.28 Object[] items;
398     int n, len;
399     if ((items = array) != null && (len = items.length) > 0) {
400     if ((n = count) > len)
401     n = len;
402     int fence = bound < 0 || bound > n ? n : bound;
403     int i = (origin < 0) ? 0 : origin;
404     if (i != fence) {
405     StringBuilder sb = new StringBuilder();
406     sb.append('[');
407     for (;;) {
408     Object e = items[i];
409 jsr166 1.30 sb.append((e == this) ? "(this Collection)" : e.toString());
410 dl 1.28 if (++i < fence)
411     sb.append(',').append(' ');
412     else
413     return sb.append(']').toString();
414 dl 1.1 }
415     }
416     }
417 dl 1.28 return "[]";
418 dl 1.1 }
419    
420 dl 1.2 final Object[] internalToArray(int origin, int bound) {
421 dl 1.28 Object[] items;
422     int n, len;
423     if ((items = array) != null && (len = items.length) > 0) {
424     if (origin < 0)
425     origin = 0;
426     if ((n = count) > len)
427     n = len;
428     int fence = bound < 0 || bound > n ? n : bound;
429     int i = (origin < 0) ? 0 : origin;
430 jsr166 1.29 if (i != fence)
431 dl 1.28 return Arrays.copyOfRange(items, i, fence, Object[].class);
432 dl 1.1 }
433 dl 1.28 return new Object[0];
434 dl 1.1 }
435    
436 jsr166 1.14 @SuppressWarnings("unchecked")
437 dl 1.2 final <T> T[] internalToArray(T[] a, int origin, int bound) {
438     int alen = a.length;
439 dl 1.28 Object[] items;
440     int n, len;
441     if ((items = array) != null && (len = items.length) > 0) {
442     if (origin < 0)
443     origin = 0;
444     if ((n = count) > len)
445     n = len;
446     int fence = bound < 0 || bound > n ? n : bound;
447     int i = (origin < 0) ? 0 : origin;
448     int rlen = fence - origin;
449     if (rlen > 0) {
450     if (alen >= rlen) {
451     System.arraycopy(items, 0, a, origin, rlen);
452 dl 1.2 if (alen > rlen)
453     a[rlen] = null;
454 dl 1.28 return a;
455 dl 1.1 }
456 dl 1.28 return (T[]) Arrays.copyOfRange(items, i, fence, a.getClass());
457 dl 1.1 }
458     }
459 dl 1.28 if (alen > 0)
460     a[0] = null;
461     return a;
462 dl 1.1 }
463    
464     // public List methods
465    
466     public boolean add(E e) {
467 dl 1.28 final StampedLock lock = this.lock;
468     long stamp = lock.writeLock();
469 dl 1.1 try {
470 dl 1.4 rawAdd(e);
471 dl 1.1 } finally {
472 dl 1.28 lock.unlockWrite(stamp);
473 dl 1.1 }
474     return true;
475     }
476    
477     public void add(int index, E element) {
478 dl 1.28 final StampedLock lock = this.lock;
479     long stamp = lock.writeLock();
480 dl 1.1 try {
481 dl 1.4 rawAddAt(index, element);
482 dl 1.1 } finally {
483 dl 1.28 lock.unlockWrite(stamp);
484 dl 1.1 }
485     }
486    
487     public boolean addAll(Collection<? extends E> c) {
488     Object[] elements = c.toArray();
489     int len = elements.length;
490     if (len == 0)
491     return false;
492 dl 1.28 final StampedLock lock = this.lock;
493     long stamp = lock.writeLock();
494 dl 1.1 try {
495 dl 1.12 Object[] items = array;
496     int n = count;
497     int newCount = n + len;
498 dl 1.28 if (items == null || newCount >= items.length)
499 dl 1.12 items = grow(newCount);
500     System.arraycopy(elements, 0, items, n, len);
501 dl 1.1 count = newCount;
502     } finally {
503 dl 1.28 lock.unlockWrite(stamp);
504 dl 1.1 }
505     return true;
506     }
507    
508     public boolean addAll(int index, Collection<? extends E> c) {
509 dl 1.28 Object[] elements = c.toArray();
510 dl 1.1 boolean ret;
511 dl 1.28 final StampedLock lock = this.lock;
512     long stamp = lock.writeLock();
513 dl 1.1 try {
514 dl 1.4 ret = rawAddAllAt(index, elements);
515 dl 1.1 } finally {
516 dl 1.28 lock.unlockWrite(stamp);
517 dl 1.1 }
518     return ret;
519     }
520    
521     public void clear() {
522 dl 1.28 final StampedLock lock = this.lock;
523     long stamp = lock.writeLock();
524 dl 1.1 try {
525 dl 1.12 int n = count;
526 dl 1.11 Object[] items = array;
527 dl 1.28 if (items != null) {
528     for (int i = 0; i < n; i++)
529     items[i] = null;
530     }
531 dl 1.1 count = 0;
532     } finally {
533 dl 1.28 lock.unlockWrite(stamp);
534 dl 1.1 }
535     }
536    
537     public boolean contains(Object o) {
538     return indexOf(o, 0) >= 0;
539     }
540    
541     public boolean containsAll(Collection<?> c) {
542 dl 1.28 boolean ret;
543     final StampedLock lock = this.lock;
544     long stamp = lock.readLock();
545     try {
546     ret = internalContainsAll(c, 0, -1);
547     } finally {
548     lock.unlockRead(stamp);
549     }
550     return ret;
551 dl 1.1 }
552    
553     public boolean equals(Object o) {
554     if (o == this)
555     return true;
556     if (!(o instanceof List))
557     return false;
558 dl 1.28 final StampedLock lock = this.lock;
559     long stamp = lock.readLock();
560     try {
561     return internalEquals((List<?>)o, 0, -1);
562     } finally {
563     lock.unlockRead(stamp);
564     }
565 dl 1.1 }
566    
567     public E get(int index) {
568 dl 1.28 final StampedLock lock = this.lock;
569     long stamp = lock.tryOptimisticRead();
570     Object[] items;
571 jsr166 1.29 if (index >= 0 && (items = array) != null &&
572 dl 1.28 index < count && index < items.length) {
573     @SuppressWarnings("unchecked") E e = (E)items[index];
574     if (lock.validate(stamp))
575 jsr166 1.18 return e;
576 dl 1.1 }
577 dl 1.28 return lockedGet(index);
578 dl 1.1 }
579    
580 dl 1.28 @SuppressWarnings("unchecked") private E lockedGet(int index) {
581     boolean oobe = false;
582     E e = null;
583     final StampedLock lock = this.lock;
584     long stamp = lock.readLock();
585     try {
586     Object[] items;
587 jsr166 1.29 if ((items = array) != null && index < items.length &&
588 dl 1.28 index < count && index >= 0)
589     e = (E)items[index];
590     else
591     oobe = true;
592     } finally {
593     lock.unlockRead(stamp);
594     }
595     if (oobe)
596     throw new ArrayIndexOutOfBoundsException(index);
597 jsr166 1.34 return e;
598 dl 1.28 }
599 jsr166 1.29
600 dl 1.1 public int hashCode() {
601 dl 1.28 int h;
602     final StampedLock lock = this.lock;
603     long s = lock.readLock();
604     try {
605     h = internalHashCode(0, -1);
606     } finally {
607     lock.unlockRead(s);
608     }
609     return h;
610 dl 1.1 }
611 jsr166 1.29
612 dl 1.1 public int indexOf(Object o) {
613 dl 1.28 int idx;
614     final StampedLock lock = this.lock;
615     long stamp = lock.readLock();
616     try {
617     idx = findFirstIndex(array, o, 0, count);
618     } finally {
619     lock.unlockRead(stamp);
620     }
621     return idx;
622 dl 1.1 }
623    
624     public boolean isEmpty() {
625 dl 1.28 final StampedLock lock = this.lock;
626     long stamp = lock.tryOptimisticRead();
627     return count == 0; // no need for validation
628 dl 1.1 }
629    
630     public Iterator<E> iterator() {
631 jsr166 1.10 return new Itr<E>(this, 0);
632 dl 1.1 }
633    
634     public int lastIndexOf(Object o) {
635 dl 1.28 int idx;
636     final StampedLock lock = this.lock;
637     long stamp = lock.readLock();
638     try {
639     idx = findLastIndex(array, o, count - 1, 0);
640     } finally {
641     lock.unlockRead(stamp);
642 dl 1.1 }
643 dl 1.28 return idx;
644 dl 1.1 }
645    
646     public ListIterator<E> listIterator() {
647 jsr166 1.10 return new Itr<E>(this, 0);
648 dl 1.1 }
649    
650     public ListIterator<E> listIterator(int index) {
651 jsr166 1.10 return new Itr<E>(this, index);
652 dl 1.1 }
653    
654 dl 1.28 @SuppressWarnings("unchecked") public E remove(int index) {
655     E oldValue = null;
656     boolean oobe = false;
657     final StampedLock lock = this.lock;
658     long stamp = lock.writeLock();
659 dl 1.1 try {
660     if (index < 0 || index >= count)
661 dl 1.28 oobe = true;
662     else {
663     oldValue = (E) array[index];
664     rawRemoveAt(index);
665     }
666 dl 1.1 } finally {
667 dl 1.28 lock.unlockWrite(stamp);
668 dl 1.1 }
669 dl 1.28 if (oobe)
670     throw new ArrayIndexOutOfBoundsException(index);
671     return oldValue;
672 dl 1.1 }
673    
674     public boolean remove(Object o) {
675 dl 1.28 final StampedLock lock = this.lock;
676     long stamp = lock.writeLock();
677 dl 1.1 try {
678 dl 1.28 return rawRemoveAt(findFirstIndex(array, o, 0, count));
679 dl 1.1 } finally {
680 dl 1.28 lock.unlockWrite(stamp);
681 dl 1.1 }
682     }
683    
684     public boolean removeAll(Collection<?> c) {
685 dl 1.28 return lockedRemoveAll(c, 0, -1);
686 dl 1.1 }
687    
688     public boolean retainAll(Collection<?> c) {
689 dl 1.28 return lockedRetainAll(c, 0, -1);
690 dl 1.1 }
691    
692 dl 1.28 @SuppressWarnings("unchecked") public E set(int index, E element) {
693     E oldValue = null;
694     boolean oobe = false;
695     final StampedLock lock = this.lock;
696     long stamp = lock.writeLock();
697 dl 1.1 try {
698 dl 1.11 Object[] items = array;
699 dl 1.28 if (items == null || index < 0 || index >= count)
700     oobe = true;
701     else {
702     oldValue = (E) items[index];
703     items[index] = element;
704     }
705 dl 1.1 } finally {
706 dl 1.28 lock.unlockWrite(stamp);
707 dl 1.1 }
708 dl 1.28 if (oobe)
709     throw new ArrayIndexOutOfBoundsException(index);
710     return oldValue;
711 dl 1.1 }
712    
713     public int size() {
714 dl 1.28 final StampedLock lock = this.lock;
715     long stamp = lock.tryOptimisticRead();
716     return count; // no need for validation
717     }
718    
719     private int lockedSize() {
720     int n;
721     final StampedLock lock = this.lock;
722     long stamp = lock.readLock();
723     try {
724     n = count;
725     } finally {
726     lock.unlockRead(stamp);
727     }
728     return n;
729 dl 1.1 }
730    
731     public List<E> subList(int fromIndex, int toIndex) {
732     int ssize = toIndex - fromIndex;
733 dl 1.28 if (ssize >= 0 && fromIndex >= 0) {
734     ReadMostlyVectorSublist<E> ret = null;
735     final StampedLock lock = this.lock;
736     long stamp = lock.readLock();
737     try {
738     if (toIndex <= count)
739     ret = new ReadMostlyVectorSublist<E>(this, fromIndex, ssize);
740     } finally {
741     lock.unlockRead(stamp);
742     }
743     if (ret != null)
744     return ret;
745     }
746 jsr166 1.29
747 dl 1.28 throw new ArrayIndexOutOfBoundsException(fromIndex < 0 ? fromIndex : toIndex);
748 dl 1.1 }
749    
750     public Object[] toArray() {
751 dl 1.28 final StampedLock lock = this.lock;
752     long stamp = lock.readLock();
753     try {
754     return internalToArray(0, -1);
755     } finally {
756     lock.unlockRead(stamp);
757     }
758 dl 1.1 }
759    
760     public <T> T[] toArray(T[] a) {
761 dl 1.28 final StampedLock lock = this.lock;
762     long stamp = lock.readLock();
763     try {
764     return internalToArray(a, 0, -1);
765     } finally {
766     lock.unlockRead(stamp);
767     }
768 dl 1.1 }
769    
770     public String toString() {
771 dl 1.28 final StampedLock lock = this.lock;
772     long stamp = lock.readLock();
773     try {
774     return internalToString(0, -1);
775     } finally {
776     lock.unlockRead(stamp);
777     }
778 dl 1.1 }
779    
780     // ReadMostlyVector-only methods
781    
782     /**
783 jsr166 1.25 * Appends the element, if not present.
784 dl 1.1 *
785     * @param e element to be added to this list, if absent
786 jsr166 1.9 * @return {@code true} if the element was added
787 dl 1.1 */
788     public boolean addIfAbsent(E e) {
789 dl 1.28 boolean ret;
790     final StampedLock lock = this.lock;
791     long stamp = lock.writeLock();
792 dl 1.1 try {
793 dl 1.28 if (findFirstIndex(array, e, 0, count) < 0) {
794 dl 1.4 rawAdd(e);
795 dl 1.28 ret = true;
796 dl 1.1 }
797     else
798 dl 1.28 ret = false;
799 dl 1.1 } finally {
800 dl 1.28 lock.unlockWrite(stamp);
801 dl 1.1 }
802 dl 1.28 return ret;
803 dl 1.1 }
804    
805     /**
806     * Appends all of the elements in the specified collection that
807     * are not already contained in this list, to the end of
808     * this list, in the order that they are returned by the
809     * specified collection's iterator.
810     *
811     * @param c collection containing elements to be added to this list
812     * @return the number of elements added
813     * @throws NullPointerException if the specified collection is null
814     * @see #addIfAbsent(Object)
815     */
816     public int addAllAbsent(Collection<? extends E> c) {
817     int added = 0;
818     Object[] cs = c.toArray();
819     int clen = cs.length;
820     if (clen != 0) {
821 dl 1.28 long stamp = lock.writeLock();
822 dl 1.1 try {
823     for (int i = 0; i < clen; ++i) {
824 jsr166 1.14 @SuppressWarnings("unchecked")
825     E e = (E) cs[i];
826 dl 1.28 if (findFirstIndex(array, e, 0, count) < 0) {
827 dl 1.4 rawAdd(e);
828 dl 1.1 ++added;
829     }
830     }
831     } finally {
832 dl 1.28 lock.unlockWrite(stamp);
833 dl 1.1 }
834     }
835     return added;
836     }
837    
838 dl 1.5 /**
839     * Returns an iterator operating over a snapshot copy of the
840     * elements of this collection created upon construction of the
841     * iterator. The iterator does <em>NOT</em> support the
842 jsr166 1.9 * {@code remove} method.
843 dl 1.5 *
844     * @return an iterator over the elements in this list in proper sequence
845     */
846     public Iterator<E> snapshotIterator() {
847     return new SnapshotIterator<E>(this);
848     }
849    
850     static final class SnapshotIterator<E> implements Iterator<E> {
851 jsr166 1.14 private final Object[] items;
852     private int cursor;
853 dl 1.5 SnapshotIterator(ReadMostlyVector<E> v) { items = v.toArray(); }
854     public boolean hasNext() { return cursor < items.length; }
855 dl 1.28 @SuppressWarnings("unchecked") public E next() {
856 dl 1.5 if (cursor < items.length)
857     return (E) items[cursor++];
858     throw new NoSuchElementException();
859     }
860     public void remove() { throw new UnsupportedOperationException() ; }
861     }
862    
863 dl 1.28 /** Interface describing a void action of one argument */
864     public interface Action<A> { void apply(A a); }
865    
866     public void forEachReadOnly(Action<E> action) {
867     final StampedLock lock = this.lock;
868     long stamp = lock.readLock();
869     try {
870 jsr166 1.29 Object[] items;
871 dl 1.28 int len, n;
872     if ((items = array) != null && (len = items.length) > 0 &&
873     (n = count) <= len) {
874     for (int i = 0; i < n; ++i) {
875     @SuppressWarnings("unchecked") E e = (E)items[i];
876     action.apply(e);
877     }
878     }
879     } finally {
880     lock.unlockRead(stamp);
881     }
882     }
883    
884 dl 1.1 // Vector-only methods
885    
886     /** See {@link Vector#firstElement} */
887     public E firstElement() {
888 dl 1.28 final StampedLock lock = this.lock;
889     long stamp = lock.tryOptimisticRead();
890     Object[] items;
891     if ((items = array) != null && count > 0 && items.length > 0) {
892     @SuppressWarnings("unchecked") E e = (E)items[0];
893     if (lock.validate(stamp))
894     return e;
895     }
896     return lockedFirstElement();
897     }
898    
899     @SuppressWarnings("unchecked") private E lockedFirstElement() {
900     Object e = null;
901     boolean oobe = false;
902     final StampedLock lock = this.lock;
903     long stamp = lock.readLock();
904     try {
905 dl 1.1 Object[] items = array;
906 dl 1.28 if (items != null && count > 0 && items.length > 0)
907     e = items[0];
908     else
909     oobe = true;
910     } finally {
911     lock.unlockRead(stamp);
912 dl 1.1 }
913 dl 1.28 if (oobe)
914     throw new NoSuchElementException();
915     return (E) e;
916 dl 1.1 }
917    
918     /** See {@link Vector#lastElement} */
919     public E lastElement() {
920 dl 1.28 final StampedLock lock = this.lock;
921     long stamp = lock.tryOptimisticRead();
922     Object[] items;
923     int i;
924 jsr166 1.29 if ((items = array) != null && (i = count - 1) >= 0 &&
925 dl 1.28 i < items.length) {
926     @SuppressWarnings("unchecked") E e = (E)items[i];
927     if (lock.validate(stamp))
928     return e;
929     }
930     return lockedLastElement();
931     }
932    
933     @SuppressWarnings("unchecked") private E lockedLastElement() {
934     Object e = null;
935     boolean oobe = false;
936     final StampedLock lock = this.lock;
937     long stamp = lock.readLock();
938     try {
939 dl 1.1 Object[] items = array;
940 dl 1.28 int i = count - 1;
941     if (items != null && i >= 0 && i < items.length)
942     e = items[i];
943     else
944     oobe = true;
945     } finally {
946     lock.unlockRead(stamp);
947 dl 1.1 }
948 dl 1.28 if (oobe)
949     throw new NoSuchElementException();
950     return (E) e;
951 dl 1.1 }
952    
953     /** See {@link Vector#indexOf(Object, int)} */
954     public int indexOf(Object o, int index) {
955 dl 1.28 if (index < 0)
956     throw new ArrayIndexOutOfBoundsException(index);
957     int idx;
958     final StampedLock lock = this.lock;
959     long stamp = lock.readLock();
960     try {
961     idx = findFirstIndex(array, o, index, count);
962     } finally {
963     lock.unlockRead(stamp);
964 dl 1.1 }
965     return idx;
966     }
967    
968     /** See {@link Vector#lastIndexOf(Object, int)} */
969     public int lastIndexOf(Object o, int index) {
970 dl 1.28 boolean oobe = false;
971 jsr166 1.23 int idx = -1;
972 dl 1.28 final StampedLock lock = this.lock;
973     long stamp = lock.readLock();
974     try {
975     if (index < count)
976     idx = findLastIndex(array, o, index, 0);
977 jsr166 1.29 else
978 dl 1.28 oobe = true;
979     } finally {
980     lock.unlockRead(stamp);
981 dl 1.1 }
982 dl 1.28 if (oobe)
983     throw new ArrayIndexOutOfBoundsException(index);
984 dl 1.1 return idx;
985     }
986    
987     /** See {@link Vector#setSize} */
988     public void setSize(int newSize) {
989     if (newSize < 0)
990     throw new ArrayIndexOutOfBoundsException(newSize);
991 dl 1.28 final StampedLock lock = this.lock;
992     long stamp = lock.writeLock();
993 dl 1.1 try {
994 dl 1.28 Object[] items;
995 dl 1.2 int n = count;
996     if (newSize > n)
997 dl 1.1 grow(newSize);
998 dl 1.28 else if ((items = array) != null) {
999 dl 1.2 for (int i = newSize ; i < n ; i++)
1000 dl 1.11 items[i] = null;
1001 dl 1.1 }
1002     count = newSize;
1003     } finally {
1004 dl 1.28 lock.unlockWrite(stamp);
1005 dl 1.1 }
1006     }
1007    
1008     /** See {@link Vector#copyInto} */
1009     public void copyInto(Object[] anArray) {
1010 dl 1.28 final StampedLock lock = this.lock;
1011     long stamp = lock.writeLock();
1012 dl 1.1 try {
1013 dl 1.28 Object[] items;
1014     if ((items = array) != null)
1015     System.arraycopy(items, 0, anArray, 0, count);
1016 dl 1.1 } finally {
1017 dl 1.28 lock.unlockWrite(stamp);
1018 dl 1.1 }
1019     }
1020    
1021     /** See {@link Vector#trimToSize} */
1022     public void trimToSize() {
1023 dl 1.28 final StampedLock lock = this.lock;
1024     long stamp = lock.writeLock();
1025 dl 1.1 try {
1026 dl 1.11 Object[] items = array;
1027 dl 1.12 int n = count;
1028 dl 1.28 if (items != null && n < items.length)
1029 dl 1.12 array = Arrays.copyOf(items, n);
1030 dl 1.1 } finally {
1031 dl 1.28 lock.unlockWrite(stamp);
1032 dl 1.1 }
1033     }
1034    
1035     /** See {@link Vector#ensureCapacity} */
1036     public void ensureCapacity(int minCapacity) {
1037     if (minCapacity > 0) {
1038 dl 1.28 final StampedLock lock = this.lock;
1039     long stamp = lock.writeLock();
1040 dl 1.1 try {
1041 dl 1.28 Object[] items = array;
1042 jsr166 1.30 int cap = (items == null) ? 0 : items.length;
1043 dl 1.28 if (minCapacity - cap > 0)
1044 dl 1.1 grow(minCapacity);
1045     } finally {
1046 dl 1.28 lock.unlockWrite(stamp);
1047 dl 1.1 }
1048     }
1049     }
1050    
1051     /** See {@link Vector#elements} */
1052     public Enumeration<E> elements() {
1053 jsr166 1.10 return new Itr<E>(this, 0);
1054 dl 1.1 }
1055    
1056     /** See {@link Vector#capacity} */
1057     public int capacity() {
1058     return array.length;
1059     }
1060    
1061     /** See {@link Vector#elementAt} */
1062     public E elementAt(int index) {
1063     return get(index);
1064     }
1065    
1066     /** See {@link Vector#setElementAt} */
1067     public void setElementAt(E obj, int index) {
1068     set(index, obj);
1069     }
1070    
1071     /** See {@link Vector#removeElementAt} */
1072     public void removeElementAt(int index) {
1073     remove(index);
1074     }
1075    
1076     /** See {@link Vector#insertElementAt} */
1077     public void insertElementAt(E obj, int index) {
1078     add(index, obj);
1079     }
1080    
1081     /** See {@link Vector#addElement} */
1082     public void addElement(E obj) {
1083     add(obj);
1084     }
1085    
1086     /** See {@link Vector#removeElement} */
1087     public boolean removeElement(Object obj) {
1088     return remove(obj);
1089     }
1090    
1091     /** See {@link Vector#removeAllElements} */
1092     public void removeAllElements() {
1093     clear();
1094     }
1095    
1096     // other methods
1097    
1098 jsr166 1.10 public ReadMostlyVector<E> clone() {
1099 dl 1.1 Object[] a = null;
1100 dl 1.28 int n;
1101     final StampedLock lock = this.lock;
1102     long stamp = lock.readLock();
1103     try {
1104     Object[] items = array;
1105     if (items == null)
1106     n = 0;
1107     else {
1108     int len = items.length;
1109     if ((n = count) > len)
1110     n = len;
1111     a = Arrays.copyOf(items, n);
1112 dl 1.1 }
1113 dl 1.28 } finally {
1114     lock.unlockRead(stamp);
1115 dl 1.1 }
1116 jsr166 1.10 return new ReadMostlyVector<E>(a, n, capacityIncrement);
1117 dl 1.1 }
1118    
1119     private void writeObject(java.io.ObjectOutputStream s)
1120 dl 1.28 throws java.io.IOException {
1121     final StampedLock lock = this.lock;
1122     long stamp = lock.readLock();
1123 dl 1.1 try {
1124     s.defaultWriteObject();
1125     } finally {
1126 dl 1.28 lock.unlockRead(stamp);
1127 dl 1.1 }
1128     }
1129    
1130 jsr166 1.15 static final class Itr<E> implements ListIterator<E>, Enumeration<E> {
1131 dl 1.28 final StampedLock lock;
1132 dl 1.1 final ReadMostlyVector<E> list;
1133     Object[] items;
1134     long seq;
1135     int cursor;
1136     int fence;
1137     int lastRet;
1138    
1139     Itr(ReadMostlyVector<E> list, int index) {
1140 dl 1.28 final StampedLock lock = list.lock;
1141     long stamp = lock.readLock();
1142     try {
1143     this.list = list;
1144     this.lock = lock;
1145     this.items = list.array;
1146     this.fence = list.count;
1147     this.cursor = index;
1148     this.lastRet = -1;
1149     } finally {
1150     this.seq = lock.tryConvertToOptimisticRead(stamp);
1151     }
1152 dl 1.1 if (index < 0 || index > fence)
1153     throw new ArrayIndexOutOfBoundsException(index);
1154     }
1155    
1156 dl 1.28 public boolean hasPrevious() {
1157     return cursor > 0;
1158     }
1159    
1160     public int nextIndex() {
1161     return cursor;
1162 dl 1.1 }
1163    
1164 dl 1.28 public int previousIndex() {
1165     return cursor - 1;
1166 dl 1.1 }
1167    
1168 dl 1.28 public boolean hasNext() {
1169     return cursor < fence;
1170 dl 1.1 }
1171    
1172     public E next() {
1173 dl 1.28 int i = cursor;
1174     Object[] es = items;
1175     if (es == null || i < 0 || i >= fence || i >= es.length)
1176     throw new NoSuchElementException();
1177     @SuppressWarnings("unchecked") E e = (E)es[i];
1178     lastRet = i;
1179     cursor = i + 1;
1180     if (!lock.validate(seq))
1181     throw new ConcurrentModificationException();
1182     return e;
1183 dl 1.1 }
1184    
1185     public E previous() {
1186 dl 1.28 int i = cursor - 1;
1187     Object[] es = items;
1188     if (es == null || i < 0 || i >= fence || i >= es.length)
1189     throw new NoSuchElementException();
1190     @SuppressWarnings("unchecked") E e = (E)es[i];
1191     lastRet = i;
1192     cursor = i;
1193     if (!lock.validate(seq))
1194     throw new ConcurrentModificationException();
1195     return e;
1196 dl 1.1 }
1197    
1198     public void remove() {
1199     int i = lastRet;
1200     if (i < 0)
1201     throw new IllegalStateException();
1202 dl 1.28 if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1203     throw new ConcurrentModificationException();
1204 dl 1.1 try {
1205 dl 1.28 list.rawRemoveAt(i);
1206     fence = list.count;
1207     cursor = i;
1208     lastRet = -1;
1209 dl 1.1 } finally {
1210 dl 1.28 seq = lock.tryConvertToOptimisticRead(seq);
1211 dl 1.1 }
1212     }
1213    
1214     public void set(E e) {
1215     int i = lastRet;
1216 dl 1.28 Object[] es = items;
1217     if (es == null || i < 0 | i >= fence)
1218 dl 1.1 throw new IllegalStateException();
1219 dl 1.28 if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1220     throw new ConcurrentModificationException();
1221 dl 1.1 try {
1222 dl 1.28 es[i] = e;
1223 dl 1.1 } finally {
1224 dl 1.28 seq = lock.tryConvertToOptimisticRead(seq);
1225 dl 1.1 }
1226     }
1227    
1228     public void add(E e) {
1229     int i = cursor;
1230     if (i < 0)
1231     throw new IllegalStateException();
1232 dl 1.28 if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1233     throw new ConcurrentModificationException();
1234 dl 1.1 try {
1235 dl 1.28 list.rawAddAt(i, e);
1236     items = list.array;
1237     fence = list.count;
1238     cursor = i + 1;
1239     lastRet = -1;
1240 dl 1.1 } finally {
1241 dl 1.28 seq = lock.tryConvertToOptimisticRead(seq);
1242 dl 1.1 }
1243     }
1244    
1245     public boolean hasMoreElements() { return hasNext(); }
1246     public E nextElement() { return next(); }
1247     }
1248    
1249 jsr166 1.14 static final class ReadMostlyVectorSublist<E>
1250     implements List<E>, RandomAccess, java.io.Serializable {
1251 jsr166 1.33 private static final long serialVersionUID = 3041673470172026059L;
1252 jsr166 1.14
1253 dl 1.1 final ReadMostlyVector<E> list;
1254     final int offset;
1255     volatile int size;
1256    
1257 jsr166 1.14 ReadMostlyVectorSublist(ReadMostlyVector<E> list,
1258     int offset, int size) {
1259 dl 1.1 this.list = list;
1260     this.offset = offset;
1261     this.size = size;
1262     }
1263    
1264     private void rangeCheck(int index) {
1265     if (index < 0 || index >= size)
1266     throw new ArrayIndexOutOfBoundsException(index);
1267     }
1268    
1269     public boolean add(E element) {
1270 dl 1.28 final StampedLock lock = list.lock;
1271     long stamp = lock.writeLock();
1272 dl 1.1 try {
1273     int c = size;
1274 dl 1.4 list.rawAddAt(c + offset, element);
1275 dl 1.1 size = c + 1;
1276     } finally {
1277 dl 1.28 lock.unlockWrite(stamp);
1278 dl 1.1 }
1279     return true;
1280     }
1281    
1282     public void add(int index, E element) {
1283 dl 1.28 final StampedLock lock = list.lock;
1284     long stamp = lock.writeLock();
1285 dl 1.1 try {
1286     if (index < 0 || index > size)
1287     throw new ArrayIndexOutOfBoundsException(index);
1288 dl 1.4 list.rawAddAt(index + offset, element);
1289 dl 1.1 ++size;
1290     } finally {
1291 dl 1.28 lock.unlockWrite(stamp);
1292 dl 1.1 }
1293     }
1294    
1295     public boolean addAll(Collection<? extends E> c) {
1296     Object[] elements = c.toArray();
1297 dl 1.28 final StampedLock lock = list.lock;
1298     long stamp = lock.writeLock();
1299 dl 1.1 try {
1300     int s = size;
1301     int pc = list.count;
1302 dl 1.4 list.rawAddAllAt(offset + s, elements);
1303 jsr166 1.14 int added = list.count - pc;
1304 dl 1.1 size = s + added;
1305 jsr166 1.14 return added != 0;
1306 dl 1.1 } finally {
1307 dl 1.28 lock.unlockWrite(stamp);
1308 dl 1.1 }
1309     }
1310    
1311     public boolean addAll(int index, Collection<? extends E> c) {
1312     Object[] elements = c.toArray();
1313 dl 1.28 final StampedLock lock = list.lock;
1314     long stamp = lock.writeLock();
1315 dl 1.1 try {
1316     int s = size;
1317     if (index < 0 || index > s)
1318     throw new ArrayIndexOutOfBoundsException(index);
1319     int pc = list.count;
1320 dl 1.4 list.rawAddAllAt(index + offset, elements);
1321 jsr166 1.14 int added = list.count - pc;
1322 dl 1.1 size = s + added;
1323 jsr166 1.14 return added != 0;
1324 dl 1.1 } finally {
1325 dl 1.28 lock.unlockWrite(stamp);
1326 dl 1.1 }
1327     }
1328    
1329     public void clear() {
1330 dl 1.28 final StampedLock lock = list.lock;
1331     long stamp = lock.writeLock();
1332 dl 1.1 try {
1333 dl 1.2 list.internalClear(offset, offset + size);
1334 dl 1.1 size = 0;
1335     } finally {
1336 dl 1.28 lock.unlockWrite(stamp);
1337 dl 1.1 }
1338     }
1339    
1340     public boolean contains(Object o) {
1341     return indexOf(o) >= 0;
1342     }
1343    
1344     public boolean containsAll(Collection<?> c) {
1345 dl 1.28 final StampedLock lock = list.lock;
1346     long stamp = lock.readLock();
1347     try {
1348     return list.internalContainsAll(c, offset, offset + size);
1349     } finally {
1350     lock.unlockRead(stamp);
1351     }
1352 dl 1.1 }
1353    
1354     public boolean equals(Object o) {
1355     if (o == this)
1356     return true;
1357     if (!(o instanceof List))
1358     return false;
1359 dl 1.28 final StampedLock lock = list.lock;
1360     long stamp = lock.readLock();
1361     try {
1362     return list.internalEquals((List<?>)(o), offset, offset + size);
1363     } finally {
1364     lock.unlockRead(stamp);
1365     }
1366 dl 1.1 }
1367    
1368     public E get(int index) {
1369     if (index < 0 || index >= size)
1370     throw new ArrayIndexOutOfBoundsException(index);
1371     return list.get(index + offset);
1372     }
1373    
1374     public int hashCode() {
1375 dl 1.28 final StampedLock lock = list.lock;
1376     long stamp = lock.readLock();
1377     try {
1378     return list.internalHashCode(offset, offset + size);
1379     } finally {
1380     lock.unlockRead(stamp);
1381     }
1382 dl 1.1 }
1383    
1384     public int indexOf(Object o) {
1385 dl 1.28 final StampedLock lock = list.lock;
1386     long stamp = lock.readLock();
1387 dl 1.1 try {
1388 dl 1.28 int idx = findFirstIndex(list.array, o, offset, offset + size);
1389 dl 1.1 return idx < 0 ? -1 : idx - offset;
1390     } finally {
1391 dl 1.28 lock.unlockRead(stamp);
1392 dl 1.1 }
1393     }
1394    
1395     public boolean isEmpty() {
1396 dl 1.28 return size() == 0;
1397 dl 1.1 }
1398    
1399     public Iterator<E> iterator() {
1400 jsr166 1.10 return new SubItr<E>(this, offset);
1401 dl 1.1 }
1402    
1403     public int lastIndexOf(Object o) {
1404 dl 1.28 final StampedLock lock = list.lock;
1405     long stamp = lock.readLock();
1406 dl 1.1 try {
1407 dl 1.28 int idx = findLastIndex(list.array, o, offset + size - 1, offset);
1408 dl 1.1 return idx < 0 ? -1 : idx - offset;
1409     } finally {
1410 dl 1.28 lock.unlockRead(stamp);
1411 dl 1.1 }
1412     }
1413    
1414     public ListIterator<E> listIterator() {
1415 jsr166 1.10 return new SubItr<E>(this, offset);
1416 dl 1.1 }
1417    
1418     public ListIterator<E> listIterator(int index) {
1419 jsr166 1.10 return new SubItr<E>(this, index + offset);
1420 dl 1.1 }
1421    
1422     public E remove(int index) {
1423 dl 1.28 final StampedLock lock = list.lock;
1424     long stamp = lock.writeLock();
1425 dl 1.1 try {
1426 dl 1.4 Object[] items = list.array;
1427     int i = index + offset;
1428 dl 1.28 if (items == null || index < 0 || index >= size || i >= items.length)
1429 dl 1.1 throw new ArrayIndexOutOfBoundsException(index);
1430 dl 1.28 @SuppressWarnings("unchecked") E result = (E)items[i];
1431 dl 1.4 list.rawRemoveAt(i);
1432 dl 1.1 size--;
1433 jsr166 1.14 return result;
1434 dl 1.1 } finally {
1435 dl 1.28 lock.unlockWrite(stamp);
1436 dl 1.1 }
1437     }
1438    
1439     public boolean remove(Object o) {
1440 dl 1.28 final StampedLock lock = list.lock;
1441     long stamp = lock.writeLock();
1442 dl 1.1 try {
1443 dl 1.28 if (list.rawRemoveAt(findFirstIndex(list.array, o, offset,
1444     offset + size))) {
1445 dl 1.1 --size;
1446 jsr166 1.14 return true;
1447 dl 1.1 }
1448 jsr166 1.14 else
1449     return false;
1450 dl 1.1 } finally {
1451 dl 1.28 lock.unlockWrite(stamp);
1452 dl 1.1 }
1453     }
1454    
1455     public boolean removeAll(Collection<?> c) {
1456 dl 1.28 return list.lockedRemoveAll(c, offset, offset + size);
1457 dl 1.1 }
1458    
1459     public boolean retainAll(Collection<?> c) {
1460 dl 1.28 return list.lockedRetainAll(c, offset, offset + size);
1461 dl 1.1 }
1462    
1463     public E set(int index, E element) {
1464     if (index < 0 || index >= size)
1465     throw new ArrayIndexOutOfBoundsException(index);
1466     return list.set(index+offset, element);
1467     }
1468    
1469     public int size() {
1470     return size;
1471     }
1472    
1473     public List<E> subList(int fromIndex, int toIndex) {
1474     int c = size;
1475     int ssize = toIndex - fromIndex;
1476 dl 1.28 if (fromIndex < 0)
1477     throw new ArrayIndexOutOfBoundsException(fromIndex);
1478     if (toIndex > c || ssize < 0)
1479     throw new ArrayIndexOutOfBoundsException(toIndex);
1480 jsr166 1.10 return new ReadMostlyVectorSublist<E>(list, offset+fromIndex, ssize);
1481 dl 1.1 }
1482    
1483     public Object[] toArray() {
1484 dl 1.28 final StampedLock lock = list.lock;
1485     long stamp = lock.readLock();
1486     try {
1487     return list.internalToArray(offset, offset + size);
1488     } finally {
1489     lock.unlockRead(stamp);
1490     }
1491 dl 1.1 }
1492    
1493     public <T> T[] toArray(T[] a) {
1494 dl 1.28 final StampedLock lock = list.lock;
1495     long stamp = lock.readLock();
1496     try {
1497     return list.internalToArray(a, offset, offset + size);
1498     } finally {
1499     lock.unlockRead(stamp);
1500     }
1501 dl 1.1 }
1502    
1503     public String toString() {
1504 dl 1.28 final StampedLock lock = list.lock;
1505     long stamp = lock.readLock();
1506     try {
1507     return list.internalToString(offset, offset + size);
1508     } finally {
1509     lock.unlockRead(stamp);
1510     }
1511 dl 1.1 }
1512    
1513     }
1514    
1515     static final class SubItr<E> implements ListIterator<E> {
1516     final ReadMostlyVectorSublist<E> sublist;
1517     final ReadMostlyVector<E> list;
1518 dl 1.28 final StampedLock lock;
1519 dl 1.1 Object[] items;
1520     long seq;
1521     int cursor;
1522 dl 1.28 int origin;
1523 dl 1.1 int fence;
1524     int lastRet;
1525    
1526     SubItr(ReadMostlyVectorSublist<E> sublist, int index) {
1527 dl 1.28 final StampedLock lock = sublist.list.lock;
1528     long stamp = lock.readLock();
1529     try {
1530     this.sublist = sublist;
1531     this.list = sublist.list;
1532     this.lock = lock;
1533     this.cursor = index;
1534     this.origin = sublist.offset;
1535     this.fence = origin + sublist.size;
1536     this.lastRet = -1;
1537     } finally {
1538     this.seq = lock.tryConvertToOptimisticRead(stamp);
1539     }
1540     if (index < 0 || cursor > fence)
1541 dl 1.1 throw new ArrayIndexOutOfBoundsException(index);
1542     }
1543    
1544 dl 1.28 public int nextIndex() {
1545     return cursor - origin;
1546     }
1547    
1548     public int previousIndex() {
1549     return cursor - origin - 1;
1550 dl 1.1 }
1551    
1552     public boolean hasNext() {
1553 dl 1.28 return cursor < fence;
1554 dl 1.1 }
1555    
1556     public boolean hasPrevious() {
1557 dl 1.28 return cursor > origin;
1558 dl 1.1 }
1559    
1560     public E next() {
1561 dl 1.28 int i = cursor;
1562     Object[] es = items;
1563     if (es == null || i < origin || i >= fence || i >= es.length)
1564     throw new NoSuchElementException();
1565     @SuppressWarnings("unchecked") E e = (E)es[i];
1566     lastRet = i;
1567     cursor = i + 1;
1568     if (!lock.validate(seq))
1569     throw new ConcurrentModificationException();
1570     return e;
1571 dl 1.1 }
1572    
1573     public E previous() {
1574 dl 1.28 int i = cursor - 1;
1575     Object[] es = items;
1576     if (es == null || i < 0 || i >= fence || i >= es.length)
1577     throw new NoSuchElementException();
1578     @SuppressWarnings("unchecked") E e = (E)es[i];
1579     lastRet = i;
1580     cursor = i;
1581     if (!lock.validate(seq))
1582     throw new ConcurrentModificationException();
1583     return e;
1584 dl 1.1 }
1585    
1586     public void remove() {
1587     int i = lastRet;
1588     if (i < 0)
1589     throw new IllegalStateException();
1590 dl 1.28 if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1591     throw new ConcurrentModificationException();
1592 dl 1.1 try {
1593 dl 1.28 list.rawRemoveAt(i);
1594     fence = origin + sublist.size;
1595     cursor = i;
1596     lastRet = -1;
1597 dl 1.1 } finally {
1598 dl 1.28 seq = lock.tryConvertToOptimisticRead(seq);
1599 dl 1.1 }
1600     }
1601    
1602     public void set(E e) {
1603     int i = lastRet;
1604 dl 1.28 if (i < origin || i >= fence)
1605 dl 1.1 throw new IllegalStateException();
1606 dl 1.28 if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1607     throw new ConcurrentModificationException();
1608 dl 1.1 try {
1609 dl 1.28 list.set(i, e);
1610 dl 1.1 } finally {
1611 dl 1.28 seq = lock.tryConvertToOptimisticRead(seq);
1612 dl 1.1 }
1613     }
1614    
1615     public void add(E e) {
1616     int i = cursor;
1617 dl 1.28 if (i < origin || i >= fence)
1618 dl 1.1 throw new IllegalStateException();
1619 dl 1.28 if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1620     throw new ConcurrentModificationException();
1621 dl 1.1 try {
1622 dl 1.28 list.rawAddAt(i, e);
1623     items = list.array;
1624     fence = origin + sublist.size;
1625     cursor = i + 1;
1626     lastRet = -1;
1627 dl 1.1 } finally {
1628 dl 1.28 seq = lock.tryConvertToOptimisticRead(seq);
1629 dl 1.1 }
1630     }
1631     }
1632     }