ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.25
Committed: Tue Feb 21 01:54:03 2012 UTC (12 years, 3 months ago) by jsr166
Branch: MAIN
Changes since 1.24: +1 -1 lines
Log Message:
use third person in javadoc first sentence

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