ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.32
Committed: Mon Nov 19 01:12:11 2012 UTC (11 years, 6 months ago) by jsr166
Branch: MAIN
Changes since 1.31: +0 -1 lines
Log Message:
javadoc style

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