ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.5
Committed: Sat Jul 16 16:05:32 2011 UTC (12 years, 11 months ago) by dl
Branch: MAIN
Changes since 1.4: +29 -1 lines
Log Message:
Add snapshotIterator

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