ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.7
Committed: Mon Jul 18 14:44:32 2011 UTC (12 years, 10 months ago) by dl
Branch: MAIN
Changes since 1.6: +37 -34 lines
Log Message:
Minor improvements

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 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     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 jsr166 1.6 int idx = (locked ?
339 dl 1.4 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 dl 1.7 for (;;) {
663     long seq = lock.awaitAvailability();
664     Object[] items = array;
665     int n = count;
666     if (n <= items.length) {
667     for (int i = 0; i < n; ++i) {
668     Object e = items[i];
669     if (lock.getSequence() != seq) {
670     lock.lock();
671     try {
672     return rawIndexOf(o, 0, count);
673     } finally {
674     lock.unlock();
675     }
676     }
677     else if ((o == null) ? e == null : o.equals(e))
678 dl 1.4 return i;
679     }
680 dl 1.7 return -1;
681 dl 1.4 }
682 dl 1.1 }
683     }
684    
685     public boolean isEmpty() {
686     long ignore = lock.getSequence();
687     return count == 0;
688     }
689    
690     public Iterator<E> iterator() {
691     return new Itr(this, 0);
692     }
693    
694     public int lastIndexOf(Object o) {
695     SequenceLock lock = this.lock;
696 dl 1.7 for (;;) {
697     long seq = lock.awaitAvailability();
698     Object[] items = array;
699     int n = count;
700     if (n <= items.length) {
701     for (int i = n - 1; i >= 0; --i) {
702     Object e = items[i];
703     if (lock.getSequence() != seq) {
704     lock.lock();
705     try {
706     return rawLastIndexOf(o, 0, count);
707     } finally {
708     lock.unlock();
709     }
710     }
711     else if ((o == null) ? e == null : o.equals(e))
712     return i;
713     }
714     return -1;
715     }
716 dl 1.1 }
717     }
718    
719     public ListIterator<E> listIterator() {
720     return new Itr(this, 0);
721     }
722    
723     public ListIterator<E> listIterator(int index) {
724     return new Itr(this, index);
725     }
726    
727     public E remove(int index) {
728     SequenceLock lock = this.lock;
729 dl 1.2 Object oldValue;
730 dl 1.1 lock.lock();
731     try {
732     if (index < 0 || index >= count)
733     throw new ArrayIndexOutOfBoundsException(index);
734 dl 1.2 oldValue = array[index];
735 dl 1.4 rawRemoveAt(index);
736 dl 1.1 } finally {
737     lock.unlock();
738     }
739 dl 1.2 return (E)oldValue;
740 dl 1.1 }
741    
742     public boolean remove(Object o) {
743     SequenceLock lock = this.lock;
744     boolean removed;
745     lock.lock();
746     try {
747 dl 1.4 removed = rawRemoveAt(rawIndexOf(o, 0, count));
748 dl 1.1 } finally {
749     lock.unlock();
750     }
751     return removed;
752     }
753    
754     public boolean removeAll(Collection<?> c) {
755     return internalRemoveAll(c, 0, -1);
756     }
757    
758     public boolean retainAll(Collection<?> c) {
759     return internalRetainAll(c, 0, -1);
760     }
761    
762     public E set(int index, E element) {
763 dl 1.2 Object oldValue;
764 dl 1.1 SequenceLock lock = this.lock;
765     lock.lock();
766     try {
767     if (index < 0 || index >= count)
768     throw new ArrayIndexOutOfBoundsException(index);
769 dl 1.2 oldValue = array[index];
770 dl 1.1 array[index] = element;
771     } finally {
772     lock.unlock();
773     }
774 dl 1.2 return (E)oldValue;
775 dl 1.1 }
776    
777     public int size() {
778     long ignore = lock.getSequence();
779     return count;
780     }
781    
782     public List<E> subList(int fromIndex, int toIndex) {
783     int c = size();
784     int ssize = toIndex - fromIndex;
785     if (fromIndex < 0 || toIndex > c || ssize < 0)
786     throw new IndexOutOfBoundsException();
787     return new ReadMostlyVectorSublist(this, fromIndex, ssize);
788     }
789    
790     public Object[] toArray() {
791     return internalToArray(0, -1);
792     }
793    
794     public <T> T[] toArray(T[] a) {
795     return internalToArray(a, 0, -1);
796     }
797    
798     public String toString() {
799     return internalToString(0, -1);
800     }
801    
802     // ReadMostlyVector-only methods
803    
804     /**
805     * Append the element if not present.
806     *
807     * @param e element to be added to this list, if absent
808     * @return <tt>true</tt> if the element was added
809     */
810     public boolean addIfAbsent(E e) {
811     boolean added;
812     SequenceLock lock = this.lock;
813     lock.lock();
814     try {
815 dl 1.2 if (rawIndexOf(e, 0, count) < 0) {
816 dl 1.4 rawAdd(e);
817 dl 1.1 added = true;
818     }
819     else
820     added = false;
821     } finally {
822     lock.unlock();
823     }
824     return added;
825     }
826    
827     /**
828     * Appends all of the elements in the specified collection that
829     * are not already contained in this list, to the end of
830     * this list, in the order that they are returned by the
831     * specified collection's iterator.
832     *
833     * @param c collection containing elements to be added to this list
834     * @return the number of elements added
835     * @throws NullPointerException if the specified collection is null
836     * @see #addIfAbsent(Object)
837     */
838     public int addAllAbsent(Collection<? extends E> c) {
839     int added = 0;
840     Object[] cs = c.toArray();
841     int clen = cs.length;
842     if (clen != 0) {
843     lock.lock();
844     try {
845     for (int i = 0; i < clen; ++i) {
846     Object e = cs[i];
847 dl 1.2 if (rawIndexOf(e, 0, count) < 0) {
848 dl 1.4 rawAdd(e);
849 dl 1.1 ++added;
850     }
851     }
852     } finally {
853     lock.unlock();
854     }
855     }
856     return added;
857     }
858    
859 dl 1.5 /**
860     * Returns an iterator operating over a snapshot copy of the
861     * elements of this collection created upon construction of the
862     * iterator. The iterator does <em>NOT</em> support the
863     * <tt>remove</tt> method.
864     *
865     * @return an iterator over the elements in this list in proper sequence
866     */
867     public Iterator<E> snapshotIterator() {
868     return new SnapshotIterator<E>(this);
869     }
870    
871     static final class SnapshotIterator<E> implements Iterator<E> {
872     final Object[] items;
873     int cursor;
874     SnapshotIterator(ReadMostlyVector<E> v) { items = v.toArray(); }
875     public boolean hasNext() { return cursor < items.length; }
876     public E next() {
877     if (cursor < items.length)
878     return (E) items[cursor++];
879     throw new NoSuchElementException();
880     }
881     public void remove() { throw new UnsupportedOperationException() ; }
882     }
883    
884 dl 1.1 // Vector-only methods
885    
886     /** See {@link Vector#firstElement} */
887     public E firstElement() {
888     SequenceLock lock = this.lock;
889     for (;;) {
890     long seq = lock.awaitAvailability();
891     Object[] items = array;
892     int len = items.length;
893 dl 1.2 int n = count;
894     if (n > len)
895 dl 1.1 continue;
896 dl 1.2 Object e; boolean ex;
897     if (n > 0) {
898     e = items[0];
899     ex = false;
900     }
901     else {
902 dl 1.1 e = null;
903     ex = true;
904     }
905     if (lock.getSequence() == seq) {
906     if (ex)
907     throw new NoSuchElementException();
908     else
909 dl 1.2 return (E)e;
910 dl 1.1 }
911     }
912     }
913    
914     /** See {@link Vector#lastElement} */
915     public E lastElement() {
916     SequenceLock lock = this.lock;
917     for (;;) {
918     long seq = lock.awaitAvailability();
919     Object[] items = array;
920     int len = items.length;
921 dl 1.2 int n = count;
922     if (n > len)
923 dl 1.1 continue;
924 dl 1.2 Object e; boolean ex;
925     if (n > 0) {
926     e = items[n - 1];
927     ex = false;
928     }
929     else {
930 dl 1.1 e = null;
931     ex = true;
932     }
933     if (lock.getSequence() == seq) {
934     if (ex)
935     throw new NoSuchElementException();
936     else
937 dl 1.2 return (E)e;
938 dl 1.1 }
939     }
940     }
941    
942     /** See {@link Vector#indexOf(Object, int)} */
943     public int indexOf(Object o, int index) {
944     SequenceLock lock = this.lock;
945     int idx = 0;
946     boolean ex = false;
947     long seq = lock.awaitAvailability();
948     Object[] items = array;
949 dl 1.2 int n = count;
950 dl 1.1 boolean retry = false;
951 dl 1.2 if (n > items.length)
952 dl 1.1 retry = true;
953     else if (index < 0)
954     ex = true;
955     else
956 dl 1.2 idx = validatedIndexOf(o, items, index, n, seq);
957 dl 1.1 if (retry || lock.getSequence() != seq) {
958     lock.lock();
959     try {
960     if (index < 0)
961     ex = true;
962     else
963 dl 1.2 idx = rawIndexOf(o, 0, count);
964 dl 1.1 } finally {
965     lock.unlock();
966     }
967     }
968     if (ex)
969     throw new ArrayIndexOutOfBoundsException(index);
970     return idx;
971     }
972    
973     /** See {@link Vector#lastIndexOf(Object, int)} */
974     public int lastIndexOf(Object o, int index) {
975     SequenceLock lock = this.lock;
976     int idx = 0;
977     boolean ex = false;
978     long seq = lock.awaitAvailability();
979     Object[] items = array;
980 dl 1.2 int n = count;
981 dl 1.1 boolean retry = false;
982 dl 1.2 if (n > items.length)
983 dl 1.1 retry = true;
984 dl 1.2 else if (index >= n)
985 dl 1.1 ex = true;
986     else
987 dl 1.2 idx = validatedLastIndexOf(o, items, index, 0, seq);
988 dl 1.1 if (retry || lock.getSequence() != seq) {
989     lock.lock();
990     try {
991     if (index >= count)
992     ex = true;
993     else
994 dl 1.2 idx = rawLastIndexOf(o, index, 0);
995 dl 1.1 } finally {
996     lock.unlock();
997     }
998     }
999     if (ex)
1000     throw new ArrayIndexOutOfBoundsException(index);
1001     return idx;
1002     }
1003    
1004     /** See {@link Vector#setSize} */
1005     public void setSize(int newSize) {
1006     if (newSize < 0)
1007     throw new ArrayIndexOutOfBoundsException(newSize);
1008     SequenceLock lock = this.lock;
1009     lock.lock();
1010     try {
1011 dl 1.2 int n = count;
1012     if (newSize > n)
1013 dl 1.1 grow(newSize);
1014     else {
1015 dl 1.2 for (int i = newSize ; i < n ; i++)
1016 dl 1.1 array[i] = null;
1017     }
1018     count = newSize;
1019     } finally {
1020     lock.unlock();
1021     }
1022     }
1023    
1024     /** See {@link Vector#copyInto} */
1025     public void copyInto(Object[] anArray) {
1026     SequenceLock lock = this.lock;
1027     lock.lock();
1028     try {
1029     System.arraycopy(array, 0, anArray, 0, count);
1030     } finally {
1031     lock.unlock();
1032     }
1033     }
1034    
1035     /** See {@link Vector#trimToSize} */
1036     public void trimToSize() {
1037     SequenceLock lock = this.lock;
1038     lock.lock();
1039     try {
1040     if (count < array.length)
1041     array = Arrays.copyOf(array, count);
1042     } finally {
1043     lock.unlock();
1044     }
1045     }
1046    
1047     /** See {@link Vector#ensureCapacity} */
1048     public void ensureCapacity(int minCapacity) {
1049     if (minCapacity > 0) {
1050     SequenceLock lock = this.lock;
1051     lock.lock();
1052     try {
1053     if (minCapacity - array.length > 0)
1054     grow(minCapacity);
1055     } finally {
1056     lock.unlock();
1057     }
1058     }
1059     }
1060    
1061     /** See {@link Vector#elements} */
1062     public Enumeration<E> elements() {
1063     return new Itr(this, 0);
1064     }
1065    
1066     /** See {@link Vector#capacity} */
1067     public int capacity() {
1068     long ignore = lock.getSequence();
1069     return array.length;
1070     }
1071    
1072     /** See {@link Vector#elementAt} */
1073     public E elementAt(int index) {
1074     return get(index);
1075     }
1076    
1077     /** See {@link Vector#setElementAt} */
1078     public void setElementAt(E obj, int index) {
1079     set(index, obj);
1080     }
1081    
1082     /** See {@link Vector#removeElementAt} */
1083     public void removeElementAt(int index) {
1084     remove(index);
1085     }
1086    
1087     /** See {@link Vector#insertElementAt} */
1088     public void insertElementAt(E obj, int index) {
1089     add(index, obj);
1090     }
1091    
1092     /** See {@link Vector#addElement} */
1093     public void addElement(E obj) {
1094     add(obj);
1095     }
1096    
1097     /** See {@link Vector#removeElement} */
1098     public boolean removeElement(Object obj) {
1099     return remove(obj);
1100     }
1101    
1102     /** See {@link Vector#removeAllElements} */
1103     public void removeAllElements() {
1104     clear();
1105     }
1106    
1107     // other methods
1108    
1109     public Object clone() {
1110     SequenceLock lock = this.lock;
1111     Object[] a = null;
1112     boolean retry = false;
1113     long seq = lock.awaitAvailability();
1114     Object[] items = array;
1115 dl 1.2 int n = count;
1116     if (n <= items.length)
1117     a = Arrays.copyOf(items, n);
1118 dl 1.1 else
1119     retry = true;
1120     if (retry || lock.getSequence() != seq) {
1121     lock.lock();
1122     try {
1123 dl 1.2 n = count;
1124     a = Arrays.copyOf(array, n);
1125 dl 1.1 } finally {
1126     lock.unlock();
1127     }
1128     }
1129 dl 1.2 return new ReadMostlyVector(a, n, capacityIncrement);
1130 dl 1.1 }
1131    
1132     private void writeObject(java.io.ObjectOutputStream s)
1133     throws java.io.IOException {
1134     SequenceLock lock = this.lock;
1135     lock.lock();
1136     try {
1137     s.defaultWriteObject();
1138     } finally {
1139     lock.unlock();
1140     }
1141     }
1142    
1143     static final class Itr<E> implements ListIterator<E>, Enumeration<E> {
1144     final ReadMostlyVector<E> list;
1145     final SequenceLock lock;
1146     Object[] items;
1147     Object next, prev;
1148     long seq;
1149     int cursor;
1150     int fence;
1151     int lastRet;
1152 dl 1.2 boolean validNext, validPrev;
1153 dl 1.1
1154     Itr(ReadMostlyVector<E> list, int index) {
1155     this.list = list;
1156     this.lock = list.lock;
1157     this.cursor = index;
1158     this.lastRet = -1;
1159     refresh();
1160     if (index < 0 || index > fence)
1161     throw new ArrayIndexOutOfBoundsException(index);
1162     }
1163    
1164     private void refresh() {
1165 dl 1.2 validNext = validPrev = false;
1166 dl 1.1 do {
1167     seq = lock.awaitAvailability();
1168     items = list.array;
1169 dl 1.2 } while ((fence = list.count) > items.length ||
1170     lock.getSequence() != seq);
1171 dl 1.1 }
1172    
1173     public boolean hasNext() {
1174 dl 1.2 boolean valid;
1175 dl 1.1 int i = cursor;
1176 dl 1.2 for (;;) {
1177     if (i >= fence || i < 0 || i >= items.length) {
1178     valid = false;
1179     break;
1180     }
1181     next = items[i];
1182 dl 1.1 if (lock.getSequence() == seq) {
1183 dl 1.2 valid = true;
1184     break;
1185 dl 1.1 }
1186     refresh();
1187     }
1188 dl 1.2 return validNext = valid;
1189 dl 1.1 }
1190    
1191     public boolean hasPrevious() {
1192 dl 1.2 boolean valid;
1193     int i = cursor - 1;
1194     for (;;) {
1195     if (i >= fence || i < 0 || i >= items.length) {
1196     valid = false;
1197     break;
1198     }
1199     prev = items[i];
1200 dl 1.1 if (lock.getSequence() == seq) {
1201 dl 1.2 valid = true;
1202     break;
1203 dl 1.1 }
1204     refresh();
1205     }
1206 dl 1.2 return validPrev = valid;
1207 dl 1.1 }
1208    
1209     public E next() {
1210 dl 1.2 if (validNext || hasNext()) {
1211     validNext = false;
1212     lastRet = cursor++;
1213     return (E) next;
1214     }
1215     throw new NoSuchElementException();
1216 dl 1.1 }
1217    
1218     public E previous() {
1219 dl 1.2 if (validPrev || hasPrevious()) {
1220     validPrev = false;
1221     lastRet = cursor--;
1222     return (E) prev;
1223     }
1224     throw new NoSuchElementException();
1225 dl 1.1 }
1226    
1227     public void remove() {
1228     int i = lastRet;
1229     if (i < 0)
1230     throw new IllegalStateException();
1231     lock.lock();
1232     try {
1233     if (i < list.count)
1234     list.remove(i);
1235     } finally {
1236     lock.unlock();
1237     }
1238     cursor = i;
1239     lastRet = -1;
1240     refresh();
1241     }
1242    
1243     public void set(E e) {
1244     int i = lastRet;
1245     if (i < 0)
1246     throw new IllegalStateException();
1247     lock.lock();
1248     try {
1249     if (i < list.count)
1250     list.set(i, e);
1251     } finally {
1252     lock.unlock();
1253     }
1254     refresh();
1255     }
1256    
1257     public void add(E e) {
1258     int i = cursor;
1259     if (i < 0)
1260     throw new IllegalStateException();
1261     lock.lock();
1262     try {
1263     if (i <= list.count)
1264     list.add(i, e);
1265     } finally {
1266     lock.unlock();
1267     }
1268     cursor = i + 1;
1269     lastRet = -1;
1270     refresh();
1271     }
1272    
1273     public boolean hasMoreElements() { return hasNext(); }
1274     public E nextElement() { return next(); }
1275     public int nextIndex() { return cursor; }
1276     public int previousIndex() { return cursor - 1; }
1277     }
1278    
1279     static final class ReadMostlyVectorSublist<E> implements List<E>, RandomAccess, java.io.Serializable {
1280     final ReadMostlyVector<E> list;
1281     final int offset;
1282     volatile int size;
1283    
1284     ReadMostlyVectorSublist(ReadMostlyVector<E> list, int offset, int size) {
1285     this.list = list;
1286     this.offset = offset;
1287     this.size = size;
1288     }
1289    
1290     private void rangeCheck(int index) {
1291     if (index < 0 || index >= size)
1292     throw new ArrayIndexOutOfBoundsException(index);
1293     }
1294    
1295     public boolean add(E element) {
1296     SequenceLock lock = list.lock;
1297     lock.lock();
1298     try {
1299     int c = size;
1300 dl 1.4 list.rawAddAt(c + offset, element);
1301 dl 1.1 size = c + 1;
1302     } finally {
1303     lock.unlock();
1304     }
1305     return true;
1306     }
1307    
1308     public void add(int index, E element) {
1309     SequenceLock lock = list.lock;
1310     lock.lock();
1311     try {
1312     if (index < 0 || index > size)
1313     throw new ArrayIndexOutOfBoundsException(index);
1314 dl 1.4 list.rawAddAt(index + offset, element);
1315 dl 1.1 ++size;
1316     } finally {
1317     lock.unlock();
1318     }
1319     }
1320    
1321     public boolean addAll(Collection<? extends E> c) {
1322     Object[] elements = c.toArray();
1323     int added;
1324     SequenceLock lock = list.lock;
1325     lock.lock();
1326     try {
1327     int s = size;
1328     int pc = list.count;
1329 dl 1.4 list.rawAddAllAt(offset + s, elements);
1330 dl 1.1 added = list.count - pc;
1331     size = s + added;
1332     } finally {
1333     lock.unlock();
1334     }
1335     return added != 0;
1336     }
1337    
1338     public boolean addAll(int index, Collection<? extends E> c) {
1339     Object[] elements = c.toArray();
1340     int added;
1341     SequenceLock lock = list.lock;
1342     lock.lock();
1343     try {
1344     int s = size;
1345     if (index < 0 || index > s)
1346     throw new ArrayIndexOutOfBoundsException(index);
1347     int pc = list.count;
1348 dl 1.4 list.rawAddAllAt(index + offset, elements);
1349 dl 1.1 added = list.count - pc;
1350     size = s + added;
1351     } finally {
1352     lock.unlock();
1353     }
1354     return added != 0;
1355     }
1356    
1357     public void clear() {
1358     SequenceLock lock = list.lock;
1359     lock.lock();
1360     try {
1361 dl 1.2 list.internalClear(offset, offset + size);
1362 dl 1.1 size = 0;
1363     } finally {
1364     lock.unlock();
1365     }
1366     }
1367    
1368     public boolean contains(Object o) {
1369     return indexOf(o) >= 0;
1370     }
1371    
1372     public boolean containsAll(Collection<?> c) {
1373 dl 1.2 return list.internalContainsAll(c, offset, offset + size);
1374 dl 1.1 }
1375    
1376     public boolean equals(Object o) {
1377     if (o == this)
1378     return true;
1379     if (!(o instanceof List))
1380     return false;
1381 dl 1.2 return list.internalEquals((List<?>)(o), offset, offset + size);
1382 dl 1.1 }
1383    
1384     public E get(int index) {
1385     if (index < 0 || index >= size)
1386     throw new ArrayIndexOutOfBoundsException(index);
1387     return list.get(index + offset);
1388     }
1389    
1390     public int hashCode() {
1391 dl 1.2 return list.internalHashCode(offset, offset + size);
1392 dl 1.1 }
1393    
1394     public int indexOf(Object o) {
1395     SequenceLock lock = list.lock;
1396     long seq = lock.awaitAvailability();
1397     Object[] items = list.array;
1398     int c = list.count;
1399     if (c <= items.length) {
1400 dl 1.4 int idx = list.validatedIndexOf(o, items, offset,
1401     offset + size, seq);
1402 dl 1.1 if (lock.getSequence() == seq)
1403     return idx < 0 ? -1 : idx - offset;
1404     }
1405     lock.lock();
1406     try {
1407 dl 1.4 int idx = list.rawIndexOf(o, offset, offset + size);
1408 dl 1.1 return idx < 0 ? -1 : idx - offset;
1409     } finally {
1410     lock.unlock();
1411     }
1412     }
1413    
1414     public boolean isEmpty() {
1415     return size == 0;
1416     }
1417    
1418     public Iterator<E> iterator() {
1419     return new SubItr(this, offset);
1420     }
1421    
1422     public int lastIndexOf(Object o) {
1423     SequenceLock lock = list.lock;
1424     long seq = lock.awaitAvailability();
1425     Object[] items = list.array;
1426     int c = list.count;
1427     if (c <= items.length) {
1428 jsr166 1.3 int idx = list.validatedLastIndexOf(o, items, offset+size-1,
1429 dl 1.2 offset, seq);
1430 dl 1.1 if (lock.getSequence() == seq)
1431     return idx < 0 ? -1 : idx - offset;
1432     }
1433     lock.lock();
1434     try {
1435 dl 1.2 int idx = list.rawLastIndexOf(o, offset + size - 1, offset);
1436 dl 1.1 return idx < 0 ? -1 : idx - offset;
1437     } finally {
1438     lock.unlock();
1439     }
1440     }
1441    
1442     public ListIterator<E> listIterator() {
1443     return new SubItr(this, offset);
1444     }
1445    
1446     public ListIterator<E> listIterator(int index) {
1447     return new SubItr(this, index + offset);
1448     }
1449    
1450     public E remove(int index) {
1451 dl 1.2 Object result;
1452 dl 1.1 SequenceLock lock = list.lock;
1453     lock.lock();
1454     try {
1455 dl 1.4 Object[] items = list.array;
1456     int i = index + offset;
1457     if (index < 0 || index >= size || i >= items.length)
1458 dl 1.1 throw new ArrayIndexOutOfBoundsException(index);
1459 dl 1.4 result = items[i];
1460     list.rawRemoveAt(i);
1461 dl 1.1 size--;
1462     } finally {
1463     lock.unlock();
1464     }
1465 dl 1.2 return (E)result;
1466 dl 1.1 }
1467    
1468     public boolean remove(Object o) {
1469     boolean removed = false;
1470     SequenceLock lock = list.lock;
1471     lock.lock();
1472     try {
1473 dl 1.4 if (list.rawRemoveAt(list.rawIndexOf(o, offset,
1474     offset + size))) {
1475 dl 1.1 removed = true;
1476     --size;
1477     }
1478     } finally {
1479     lock.unlock();
1480     }
1481     return removed;
1482     }
1483    
1484     public boolean removeAll(Collection<?> c) {
1485 dl 1.2 return list.internalRemoveAll(c, offset, offset + size);
1486 dl 1.1 }
1487    
1488     public boolean retainAll(Collection<?> c) {
1489 dl 1.2 return list.internalRetainAll(c, offset, offset + size);
1490 dl 1.1 }
1491    
1492     public E set(int index, E element) {
1493     if (index < 0 || index >= size)
1494     throw new ArrayIndexOutOfBoundsException(index);
1495     return list.set(index+offset, element);
1496     }
1497    
1498     public int size() {
1499     return size;
1500     }
1501    
1502     public List<E> subList(int fromIndex, int toIndex) {
1503     int c = size;
1504     int ssize = toIndex - fromIndex;
1505     if (fromIndex < 0 || toIndex > c || ssize < 0)
1506     throw new IndexOutOfBoundsException();
1507     return new ReadMostlyVectorSublist(list, offset+fromIndex, ssize);
1508     }
1509    
1510     public Object[] toArray() {
1511 dl 1.2 return list.internalToArray(offset, offset + size);
1512 dl 1.1 }
1513    
1514     public <T> T[] toArray(T[] a) {
1515 dl 1.2 return list.internalToArray(a, offset, offset + size);
1516 dl 1.1 }
1517    
1518     public String toString() {
1519 dl 1.2 return list.internalToString(offset, offset + size);
1520 dl 1.1 }
1521    
1522     }
1523    
1524     static final class SubItr<E> implements ListIterator<E> {
1525     final ReadMostlyVectorSublist<E> sublist;
1526     final ReadMostlyVector<E> list;
1527     final SequenceLock lock;
1528     Object[] items;
1529     Object next, prev;
1530     long seq;
1531     int cursor;
1532     int fence;
1533     int lastRet;
1534 dl 1.2 boolean validNext, validPrev;
1535 dl 1.1
1536     SubItr(ReadMostlyVectorSublist<E> sublist, int index) {
1537     this.sublist = sublist;
1538     this.list = sublist.list;
1539     this.lock = list.lock;
1540     this.cursor = index;
1541     this.lastRet = -1;
1542     refresh();
1543     if (index < 0 || index > fence)
1544     throw new ArrayIndexOutOfBoundsException(index);
1545     }
1546    
1547     private void refresh() {
1548 dl 1.2 validNext = validPrev = false;
1549 dl 1.1 do {
1550 dl 1.2 int n;
1551 dl 1.1 seq = lock.awaitAvailability();
1552     items = list.array;
1553 dl 1.2 if ((n = list.count) > items.length)
1554     continue;
1555 dl 1.1 int b = sublist.offset + sublist.size;
1556 dl 1.2 fence = b < n ? b : n;
1557 dl 1.1 } while (lock.getSequence() != seq);
1558     }
1559    
1560     public boolean hasNext() {
1561 dl 1.2 boolean valid;
1562 dl 1.1 int i = cursor;
1563 dl 1.2 for (;;) {
1564     if (i >= fence || i < 0 || i >= items.length) {
1565     valid = false;
1566     break;
1567     }
1568     next = items[i];
1569 dl 1.1 if (lock.getSequence() == seq) {
1570 dl 1.2 valid = true;
1571     break;
1572 dl 1.1 }
1573     refresh();
1574     }
1575 dl 1.2 return validNext = valid;
1576 dl 1.1 }
1577    
1578     public boolean hasPrevious() {
1579 dl 1.2 boolean valid;
1580     int i = cursor - 1;
1581     for (;;) {
1582     if (i >= fence || i < 0 || i >= items.length) {
1583     valid = false;
1584     break;
1585     }
1586     prev = items[i];
1587 dl 1.1 if (lock.getSequence() == seq) {
1588 dl 1.2 valid = true;
1589     break;
1590 dl 1.1 }
1591     refresh();
1592     }
1593 dl 1.2 return validPrev = valid;
1594 dl 1.1 }
1595    
1596     public E next() {
1597 dl 1.2 if (validNext || hasNext()) {
1598     validNext = false;
1599     lastRet = cursor++;
1600     return (E) next;
1601     }
1602     throw new NoSuchElementException();
1603 dl 1.1 }
1604    
1605     public E previous() {
1606 dl 1.2 if (validPrev || hasPrevious()) {
1607     validPrev = false;
1608     lastRet = cursor--;
1609     return (E) prev;
1610     }
1611     throw new NoSuchElementException();
1612 dl 1.1 }
1613    
1614     public int nextIndex() {
1615     return cursor - sublist.offset;
1616     }
1617    
1618     public int previousIndex() {
1619     return cursor - 1 - sublist.offset;
1620     }
1621    
1622     public void remove() {
1623     int i = lastRet;
1624     if (i < 0)
1625     throw new IllegalStateException();
1626     cursor = i;
1627     lastRet = -1;
1628     lock.lock();
1629     try {
1630     if (i < list.count) {
1631     list.remove(i);
1632     --sublist.size;
1633     }
1634     } finally {
1635     lock.unlock();
1636     }
1637     refresh();
1638     }
1639    
1640     public void set(E e) {
1641     int i = lastRet;
1642     if (i < 0)
1643     throw new IllegalStateException();
1644     lock.lock();
1645     try {
1646     if (i < list.count)
1647     list.set(i, e);
1648     } finally {
1649     lock.unlock();
1650     }
1651     refresh();
1652     }
1653    
1654     public void add(E e) {
1655     int i = cursor;
1656     if (i < 0)
1657     throw new IllegalStateException();
1658     cursor = i + 1;
1659     lastRet = -1;
1660     lock.lock();
1661     try {
1662     if (i <= list.count) {
1663     list.add(i, e);
1664     ++sublist.size;
1665     }
1666     } finally {
1667     lock.unlock();
1668     }
1669     refresh();
1670     }
1671    
1672     }
1673     }
1674