ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.1
Committed: Fri Jul 15 23:56:18 2011 UTC (12 years, 10 months ago) by dl
Branch: MAIN
Log Message:
Initial check-in

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