ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.16
Committed: Sat Dec 31 05:35:16 2011 UTC (12 years, 5 months ago) by jsr166
Branch: MAIN
Changes since 1.15: +1 -1 lines
Log Message:
bug fix for indexOf(Object, int)

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