ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.12
Committed: Thu Jul 21 12:49:37 2011 UTC (12 years, 10 months ago) by dl
Branch: MAIN
Changes since 1.11: +35 -31 lines
Log Message:
Improve usage guidance and sample code

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