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