ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.12
Committed: Thu Jul 21 12:49:37 2011 UTC (12 years, 10 months ago) by dl
Branch: MAIN
Changes since 1.11: +35 -31 lines
Log Message:
Improve usage guidance and sample code

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