ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.4
Committed: Sat Jul 16 15:05:04 2011 UTC (12 years, 10 months ago) by dl
Branch: MAIN
Changes since 1.3: +67 -55 lines
Log Message:
Various improvements

File Contents

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