ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.11
Committed: Wed Jul 20 20:29:33 2011 UTC (12 years, 11 months ago) by dl
Branch: MAIN
Changes since 1.10: +36 -26 lines
Log Message:
Add volatile to advice 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 void 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 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[n] = e;
207 else {
208 grow(n + 1);
209 array[n] = e;
210 }
211 count = n + 1;
212 }
213
214 final void rawAddAt(int index, Object e) {
215 int n = count;
216 if (index > n)
217 throw new ArrayIndexOutOfBoundsException(index);
218 if (n >= array.length)
219 grow(n + 1);
220 Object[] items = array;
221 if (index < n)
222 System.arraycopy(items, index, items, index + 1, n - index);
223 items[index] = e;
224 count = n + 1;
225 }
226
227 final boolean rawAddAllAt(int index, Object[] elements) {
228 int n = count;
229 if (index < 0 || index > n)
230 throw new ArrayIndexOutOfBoundsException(index);
231 int len = elements.length;
232 if (len == 0)
233 return false;
234 int newCount = n + len;
235 if (newCount >= array.length)
236 grow(newCount);
237 Object[] items = array;
238 int mv = n - index;
239 if (mv > 0)
240 System.arraycopy(items, index, items, index + len, mv);
241 System.arraycopy(elements, 0, items, index, len);
242 count = newCount;
243 return true;
244 }
245
246 final boolean rawRemoveAt(int index) {
247 Object[] items = array;
248 int n = count - 1;
249 if (index < 0 || index > n)
250 return false;
251 int mv = n - index;
252 if (mv > 0)
253 System.arraycopy(items, index + 1, items, index, mv);
254 items[n] = null;
255 count = n;
256 return true;
257 }
258
259 /**
260 * Internal version of removeAll for lists and sublists. In this
261 * and other similar methods below, the bound argument is, if
262 * non-negative, the purported upper bound of a list/sublist, or
263 * is left negative if the bound should be determined via count
264 * field under lock.
265 */
266 final boolean internalRemoveAll(Collection<?> c, int origin, int bound) {
267 SequenceLock lock = this.lock;
268 boolean removed = false;
269 lock.lock();
270 try {
271 int n = count;
272 int fence = bound < 0 || bound > n ? n : bound;
273 if (origin >= 0 && origin < fence) {
274 for (Object x : c) {
275 while (rawRemoveAt(rawIndexOf(x, origin, fence)))
276 removed = true;
277 }
278 }
279 } finally {
280 lock.unlock();
281 }
282 return removed;
283 }
284
285 final boolean internalRetainAll(Collection<?> c, int origin, int bound) {
286 SequenceLock lock = this.lock;
287 boolean removed = false;
288 if (c != this) {
289 lock.lock();
290 try {
291 Object[] items = array;
292 int i = origin;
293 int n = count;
294 int fence = bound < 0 || bound > n ? n : bound;
295 while (i >= 0 && i < fence) {
296 if (c.contains(items[i]))
297 ++i;
298 else {
299 --fence;
300 int mv = --count - i;
301 if (mv > 0)
302 System.arraycopy(items, i + 1, items, i, mv);
303 removed = true;
304 }
305 }
306 } finally {
307 lock.unlock();
308 }
309 }
310 return removed;
311 }
312
313 final void internalClear(int origin, int bound) {
314 Object[] items = array;
315 int n = count;
316 int fence = bound < 0 || bound > n ? n : bound;
317 if (origin >= 0 && origin < fence) {
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 Object[] items = array;
337 int len = items.length;
338 int n = count;
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 len = items.length;
420 int n = count;
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 len = items.length;
451 int n = count;
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 len = items.length;
498 int n = count;
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 len = items.length;
527 int n = count;
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 int newCount = count + len;
588 if (newCount >= array.length)
589 grow(newCount);
590 System.arraycopy(elements, 0, array, count, len);
591 count = newCount;
592 } finally {
593 lock.unlock();
594 }
595 return true;
596 }
597
598 public boolean addAll(int index, Collection<? extends E> c) {
599 SequenceLock lock = this.lock;
600 boolean ret;
601 Object[] elements = c.toArray();
602 lock.lock();
603 try {
604 ret = rawAddAllAt(index, elements);
605 } finally {
606 lock.unlock();
607 }
608 return ret;
609 }
610
611 public void clear() {
612 SequenceLock lock = this.lock;
613 lock.lock();
614 try {
615 Object[] items = array;
616 for (int i = 0; i < count; i++)
617 items[i] = null;
618 count = 0;
619 } finally {
620 lock.unlock();
621 }
622 }
623
624 public boolean contains(Object o) {
625 return indexOf(o, 0) >= 0;
626 }
627
628 public boolean containsAll(Collection<?> c) {
629 return internalContainsAll(c, 0, -1);
630 }
631
632 public boolean equals(Object o) {
633 if (o == this)
634 return true;
635 if (!(o instanceof List))
636 return false;
637 return internalEquals((List<?>)o, 0, -1);
638 }
639
640 public E get(int index) {
641 SequenceLock lock = this.lock;
642 for (;;) {
643 long seq = lock.awaitAvailability();
644 Object[] items = array;
645 int n = count;
646 if (n > items.length)
647 continue;
648 Object e; boolean ex;
649 if (index < 0 || index >= n) {
650 e = null;
651 ex = true;
652 }
653 else {
654 e = items[index];
655 ex = false;
656 }
657 if (lock.getSequence() == seq) {
658 if (ex)
659 throw new ArrayIndexOutOfBoundsException(index);
660 else
661 return (E)e;
662 }
663 }
664 }
665
666 public int hashCode() {
667 return internalHashCode(0, -1);
668 }
669
670 public int indexOf(Object o) {
671 SequenceLock lock = this.lock;
672 for (;;) {
673 long seq = lock.awaitAvailability();
674 Object[] items = array;
675 int n = count;
676 if (n <= items.length) {
677 for (int i = 0; i < n; ++i) {
678 Object e = items[i];
679 if (lock.getSequence() != seq) {
680 lock.lock();
681 try {
682 return rawIndexOf(o, 0, count);
683 } finally {
684 lock.unlock();
685 }
686 }
687 else if ((o == null) ? e == null : o.equals(e))
688 return i;
689 }
690 return -1;
691 }
692 }
693 }
694
695 public boolean isEmpty() {
696 return count == 0;
697 }
698
699 public Iterator<E> iterator() {
700 return new Itr<E>(this, 0);
701 }
702
703 public int lastIndexOf(Object o) {
704 SequenceLock lock = this.lock;
705 for (;;) {
706 long seq = lock.awaitAvailability();
707 Object[] items = array;
708 int n = count;
709 if (n <= items.length) {
710 for (int i = n - 1; i >= 0; --i) {
711 Object e = items[i];
712 if (lock.getSequence() != seq) {
713 lock.lock();
714 try {
715 return rawLastIndexOf(o, 0, count);
716 } finally {
717 lock.unlock();
718 }
719 }
720 else if ((o == null) ? e == null : o.equals(e))
721 return i;
722 }
723 return -1;
724 }
725 }
726 }
727
728 public ListIterator<E> listIterator() {
729 return new Itr<E>(this, 0);
730 }
731
732 public ListIterator<E> listIterator(int index) {
733 return new Itr<E>(this, index);
734 }
735
736 public E remove(int index) {
737 SequenceLock lock = this.lock;
738 Object oldValue;
739 lock.lock();
740 try {
741 if (index < 0 || index >= count)
742 throw new ArrayIndexOutOfBoundsException(index);
743 oldValue = array[index];
744 rawRemoveAt(index);
745 } finally {
746 lock.unlock();
747 }
748 return (E)oldValue;
749 }
750
751 public boolean remove(Object o) {
752 SequenceLock lock = this.lock;
753 boolean removed;
754 lock.lock();
755 try {
756 removed = rawRemoveAt(rawIndexOf(o, 0, count));
757 } finally {
758 lock.unlock();
759 }
760 return removed;
761 }
762
763 public boolean removeAll(Collection<?> c) {
764 return internalRemoveAll(c, 0, -1);
765 }
766
767 public boolean retainAll(Collection<?> c) {
768 return internalRetainAll(c, 0, -1);
769 }
770
771 public E set(int index, E element) {
772 Object oldValue;
773 SequenceLock lock = this.lock;
774 lock.lock();
775 try {
776 Object[] items = array;
777 if (index < 0 || index >= count)
778 throw new ArrayIndexOutOfBoundsException(index);
779 oldValue = items[index];
780 items[index] = element;
781 } finally {
782 lock.unlock();
783 }
784 return (E)oldValue;
785 }
786
787 public int size() {
788 return count;
789 }
790
791 public List<E> subList(int fromIndex, int toIndex) {
792 int c = size();
793 int ssize = toIndex - fromIndex;
794 if (fromIndex < 0 || toIndex > c || ssize < 0)
795 throw new IndexOutOfBoundsException();
796 return new ReadMostlyVectorSublist<E>(this, fromIndex, ssize);
797 }
798
799 public Object[] toArray() {
800 return internalToArray(0, -1);
801 }
802
803 public <T> T[] toArray(T[] a) {
804 return internalToArray(a, 0, -1);
805 }
806
807 public String toString() {
808 return internalToString(0, -1);
809 }
810
811 // ReadMostlyVector-only methods
812
813 /**
814 * Append the element if not present.
815 *
816 * @param e element to be added to this list, if absent
817 * @return {@code true} if the element was added
818 */
819 public boolean addIfAbsent(E e) {
820 boolean added;
821 SequenceLock lock = this.lock;
822 lock.lock();
823 try {
824 if (rawIndexOf(e, 0, count) < 0) {
825 rawAdd(e);
826 added = true;
827 }
828 else
829 added = false;
830 } finally {
831 lock.unlock();
832 }
833 return added;
834 }
835
836 /**
837 * Appends all of the elements in the specified collection that
838 * are not already contained in this list, to the end of
839 * this list, in the order that they are returned by the
840 * specified collection's iterator.
841 *
842 * @param c collection containing elements to be added to this list
843 * @return the number of elements added
844 * @throws NullPointerException if the specified collection is null
845 * @see #addIfAbsent(Object)
846 */
847 public int addAllAbsent(Collection<? extends E> c) {
848 int added = 0;
849 Object[] cs = c.toArray();
850 int clen = cs.length;
851 if (clen != 0) {
852 lock.lock();
853 try {
854 for (int i = 0; i < clen; ++i) {
855 Object e = cs[i];
856 if (rawIndexOf(e, 0, count) < 0) {
857 rawAdd(e);
858 ++added;
859 }
860 }
861 } finally {
862 lock.unlock();
863 }
864 }
865 return added;
866 }
867
868 /**
869 * Returns an iterator operating over a snapshot copy of the
870 * elements of this collection created upon construction of the
871 * iterator. The iterator does <em>NOT</em> support the
872 * {@code remove} method.
873 *
874 * @return an iterator over the elements in this list in proper sequence
875 */
876 public Iterator<E> snapshotIterator() {
877 return new SnapshotIterator<E>(this);
878 }
879
880 static final class SnapshotIterator<E> implements Iterator<E> {
881 final Object[] items;
882 int cursor;
883 SnapshotIterator(ReadMostlyVector<E> v) { items = v.toArray(); }
884 public boolean hasNext() { return cursor < items.length; }
885 public E next() {
886 if (cursor < items.length)
887 return (E) items[cursor++];
888 throw new NoSuchElementException();
889 }
890 public void remove() { throw new UnsupportedOperationException() ; }
891 }
892
893 // Vector-only methods
894
895 /** See {@link Vector#firstElement} */
896 public E firstElement() {
897 SequenceLock lock = this.lock;
898 for (;;) {
899 long seq = lock.awaitAvailability();
900 Object[] items = array;
901 int len = items.length;
902 int n = count;
903 if (n > len)
904 continue;
905 Object e; boolean ex;
906 if (n > 0) {
907 e = items[0];
908 ex = false;
909 }
910 else {
911 e = null;
912 ex = true;
913 }
914 if (lock.getSequence() == seq) {
915 if (ex)
916 throw new NoSuchElementException();
917 else
918 return (E)e;
919 }
920 }
921 }
922
923 /** See {@link Vector#lastElement} */
924 public E lastElement() {
925 SequenceLock lock = this.lock;
926 for (;;) {
927 long seq = lock.awaitAvailability();
928 Object[] items = array;
929 int len = items.length;
930 int n = count;
931 if (n > len)
932 continue;
933 Object e; boolean ex;
934 if (n > 0) {
935 e = items[n - 1];
936 ex = false;
937 }
938 else {
939 e = null;
940 ex = true;
941 }
942 if (lock.getSequence() == seq) {
943 if (ex)
944 throw new NoSuchElementException();
945 else
946 return (E)e;
947 }
948 }
949 }
950
951 /** See {@link Vector#indexOf(Object, int)} */
952 public int indexOf(Object o, int index) {
953 SequenceLock lock = this.lock;
954 int idx = 0;
955 boolean ex = false;
956 long seq = lock.awaitAvailability();
957 Object[] items = array;
958 int n = count;
959 boolean retry = false;
960 if (n > items.length)
961 retry = true;
962 else if (index < 0)
963 ex = true;
964 else
965 idx = validatedIndexOf(o, items, index, n, seq);
966 if (retry || lock.getSequence() != seq) {
967 lock.lock();
968 try {
969 if (index < 0)
970 ex = true;
971 else
972 idx = rawIndexOf(o, 0, count);
973 } finally {
974 lock.unlock();
975 }
976 }
977 if (ex)
978 throw new ArrayIndexOutOfBoundsException(index);
979 return idx;
980 }
981
982 /** See {@link Vector#lastIndexOf(Object, int)} */
983 public int lastIndexOf(Object o, int index) {
984 SequenceLock lock = this.lock;
985 int idx = 0;
986 boolean ex = false;
987 long seq = lock.awaitAvailability();
988 Object[] items = array;
989 int n = count;
990 boolean retry = false;
991 if (n > items.length)
992 retry = true;
993 else if (index >= n)
994 ex = true;
995 else
996 idx = validatedLastIndexOf(o, items, index, 0, seq);
997 if (retry || lock.getSequence() != seq) {
998 lock.lock();
999 try {
1000 if (index >= count)
1001 ex = true;
1002 else
1003 idx = rawLastIndexOf(o, index, 0);
1004 } finally {
1005 lock.unlock();
1006 }
1007 }
1008 if (ex)
1009 throw new ArrayIndexOutOfBoundsException(index);
1010 return idx;
1011 }
1012
1013 /** See {@link Vector#setSize} */
1014 public void setSize(int newSize) {
1015 if (newSize < 0)
1016 throw new ArrayIndexOutOfBoundsException(newSize);
1017 SequenceLock lock = this.lock;
1018 lock.lock();
1019 try {
1020 int n = count;
1021 if (newSize > n)
1022 grow(newSize);
1023 else {
1024 Object[] items = array;
1025 for (int i = newSize ; i < n ; i++)
1026 items[i] = null;
1027 }
1028 count = newSize;
1029 } finally {
1030 lock.unlock();
1031 }
1032 }
1033
1034 /** See {@link Vector#copyInto} */
1035 public void copyInto(Object[] anArray) {
1036 SequenceLock lock = this.lock;
1037 lock.lock();
1038 try {
1039 System.arraycopy(array, 0, anArray, 0, count);
1040 } finally {
1041 lock.unlock();
1042 }
1043 }
1044
1045 /** See {@link Vector#trimToSize} */
1046 public void trimToSize() {
1047 SequenceLock lock = this.lock;
1048 lock.lock();
1049 try {
1050 Object[] items = array;
1051 if (count < items.length)
1052 array = Arrays.copyOf(items, count);
1053 } finally {
1054 lock.unlock();
1055 }
1056 }
1057
1058 /** See {@link Vector#ensureCapacity} */
1059 public void ensureCapacity(int minCapacity) {
1060 if (minCapacity > 0) {
1061 SequenceLock lock = this.lock;
1062 lock.lock();
1063 try {
1064 if (minCapacity - array.length > 0)
1065 grow(minCapacity);
1066 } finally {
1067 lock.unlock();
1068 }
1069 }
1070 }
1071
1072 /** See {@link Vector#elements} */
1073 public Enumeration<E> elements() {
1074 return new Itr<E>(this, 0);
1075 }
1076
1077 /** See {@link Vector#capacity} */
1078 public int capacity() {
1079 return array.length;
1080 }
1081
1082 /** See {@link Vector#elementAt} */
1083 public E elementAt(int index) {
1084 return get(index);
1085 }
1086
1087 /** See {@link Vector#setElementAt} */
1088 public void setElementAt(E obj, int index) {
1089 set(index, obj);
1090 }
1091
1092 /** See {@link Vector#removeElementAt} */
1093 public void removeElementAt(int index) {
1094 remove(index);
1095 }
1096
1097 /** See {@link Vector#insertElementAt} */
1098 public void insertElementAt(E obj, int index) {
1099 add(index, obj);
1100 }
1101
1102 /** See {@link Vector#addElement} */
1103 public void addElement(E obj) {
1104 add(obj);
1105 }
1106
1107 /** See {@link Vector#removeElement} */
1108 public boolean removeElement(Object obj) {
1109 return remove(obj);
1110 }
1111
1112 /** See {@link Vector#removeAllElements} */
1113 public void removeAllElements() {
1114 clear();
1115 }
1116
1117 // other methods
1118
1119 public ReadMostlyVector<E> clone() {
1120 SequenceLock lock = this.lock;
1121 Object[] a = null;
1122 boolean retry = false;
1123 long seq = lock.awaitAvailability();
1124 Object[] items = array;
1125 int n = count;
1126 if (n <= items.length)
1127 a = Arrays.copyOf(items, n);
1128 else
1129 retry = true;
1130 if (retry || lock.getSequence() != seq) {
1131 lock.lock();
1132 try {
1133 n = count;
1134 a = Arrays.copyOf(array, n);
1135 } finally {
1136 lock.unlock();
1137 }
1138 }
1139 return new ReadMostlyVector<E>(a, n, capacityIncrement);
1140 }
1141
1142 private void writeObject(java.io.ObjectOutputStream s)
1143 throws java.io.IOException {
1144 SequenceLock lock = this.lock;
1145 lock.lock();
1146 try {
1147 s.defaultWriteObject();
1148 } finally {
1149 lock.unlock();
1150 }
1151 }
1152
1153 static final class Itr<E> implements ListIterator<E>, Enumeration<E> {
1154 final ReadMostlyVector<E> list;
1155 final SequenceLock lock;
1156 Object[] items;
1157 Object next, prev;
1158 long seq;
1159 int cursor;
1160 int fence;
1161 int lastRet;
1162 boolean validNext, validPrev;
1163
1164 Itr(ReadMostlyVector<E> list, int index) {
1165 this.list = list;
1166 this.lock = list.lock;
1167 this.cursor = index;
1168 this.lastRet = -1;
1169 refresh();
1170 if (index < 0 || index > fence)
1171 throw new ArrayIndexOutOfBoundsException(index);
1172 }
1173
1174 private void refresh() {
1175 validNext = validPrev = false;
1176 do {
1177 seq = lock.awaitAvailability();
1178 items = list.array;
1179 } while ((fence = list.count) > items.length ||
1180 lock.getSequence() != seq);
1181 }
1182
1183 public boolean hasNext() {
1184 boolean valid;
1185 int i = cursor;
1186 for (;;) {
1187 if (i >= fence || i < 0 || i >= items.length) {
1188 valid = false;
1189 break;
1190 }
1191 next = items[i];
1192 if (lock.getSequence() == seq) {
1193 valid = true;
1194 break;
1195 }
1196 refresh();
1197 }
1198 return validNext = valid;
1199 }
1200
1201 public boolean hasPrevious() {
1202 boolean valid;
1203 int i = cursor - 1;
1204 for (;;) {
1205 if (i >= fence || i < 0 || i >= items.length) {
1206 valid = false;
1207 break;
1208 }
1209 prev = items[i];
1210 if (lock.getSequence() == seq) {
1211 valid = true;
1212 break;
1213 }
1214 refresh();
1215 }
1216 return validPrev = valid;
1217 }
1218
1219 public E next() {
1220 if (validNext || hasNext()) {
1221 validNext = false;
1222 lastRet = cursor++;
1223 return (E) next;
1224 }
1225 throw new NoSuchElementException();
1226 }
1227
1228 public E previous() {
1229 if (validPrev || hasPrevious()) {
1230 validPrev = false;
1231 lastRet = cursor--;
1232 return (E) prev;
1233 }
1234 throw new NoSuchElementException();
1235 }
1236
1237 public void remove() {
1238 int i = lastRet;
1239 if (i < 0)
1240 throw new IllegalStateException();
1241 lock.lock();
1242 try {
1243 if (i < list.count)
1244 list.remove(i);
1245 } finally {
1246 lock.unlock();
1247 }
1248 cursor = i;
1249 lastRet = -1;
1250 refresh();
1251 }
1252
1253 public void set(E e) {
1254 int i = lastRet;
1255 if (i < 0)
1256 throw new IllegalStateException();
1257 lock.lock();
1258 try {
1259 if (i < list.count)
1260 list.set(i, e);
1261 } finally {
1262 lock.unlock();
1263 }
1264 refresh();
1265 }
1266
1267 public void add(E e) {
1268 int i = cursor;
1269 if (i < 0)
1270 throw new IllegalStateException();
1271 lock.lock();
1272 try {
1273 if (i <= list.count)
1274 list.add(i, e);
1275 } finally {
1276 lock.unlock();
1277 }
1278 cursor = i + 1;
1279 lastRet = -1;
1280 refresh();
1281 }
1282
1283 public boolean hasMoreElements() { return hasNext(); }
1284 public E nextElement() { return next(); }
1285 public int nextIndex() { return cursor; }
1286 public int previousIndex() { return cursor - 1; }
1287 }
1288
1289 static final class ReadMostlyVectorSublist<E> implements List<E>, RandomAccess, java.io.Serializable {
1290 final ReadMostlyVector<E> list;
1291 final int offset;
1292 volatile int size;
1293
1294 ReadMostlyVectorSublist(ReadMostlyVector<E> list, int offset, int size) {
1295 this.list = list;
1296 this.offset = offset;
1297 this.size = size;
1298 }
1299
1300 private void rangeCheck(int index) {
1301 if (index < 0 || index >= size)
1302 throw new ArrayIndexOutOfBoundsException(index);
1303 }
1304
1305 public boolean add(E element) {
1306 SequenceLock lock = list.lock;
1307 lock.lock();
1308 try {
1309 int c = size;
1310 list.rawAddAt(c + offset, element);
1311 size = c + 1;
1312 } finally {
1313 lock.unlock();
1314 }
1315 return true;
1316 }
1317
1318 public void add(int index, E element) {
1319 SequenceLock lock = list.lock;
1320 lock.lock();
1321 try {
1322 if (index < 0 || index > size)
1323 throw new ArrayIndexOutOfBoundsException(index);
1324 list.rawAddAt(index + offset, element);
1325 ++size;
1326 } finally {
1327 lock.unlock();
1328 }
1329 }
1330
1331 public boolean addAll(Collection<? extends E> c) {
1332 Object[] elements = c.toArray();
1333 int added;
1334 SequenceLock lock = list.lock;
1335 lock.lock();
1336 try {
1337 int s = size;
1338 int pc = list.count;
1339 list.rawAddAllAt(offset + s, elements);
1340 added = list.count - pc;
1341 size = s + added;
1342 } finally {
1343 lock.unlock();
1344 }
1345 return added != 0;
1346 }
1347
1348 public boolean addAll(int index, Collection<? extends E> c) {
1349 Object[] elements = c.toArray();
1350 int added;
1351 SequenceLock lock = list.lock;
1352 lock.lock();
1353 try {
1354 int s = size;
1355 if (index < 0 || index > s)
1356 throw new ArrayIndexOutOfBoundsException(index);
1357 int pc = list.count;
1358 list.rawAddAllAt(index + offset, elements);
1359 added = list.count - pc;
1360 size = s + added;
1361 } finally {
1362 lock.unlock();
1363 }
1364 return added != 0;
1365 }
1366
1367 public void clear() {
1368 SequenceLock lock = list.lock;
1369 lock.lock();
1370 try {
1371 list.internalClear(offset, offset + size);
1372 size = 0;
1373 } finally {
1374 lock.unlock();
1375 }
1376 }
1377
1378 public boolean contains(Object o) {
1379 return indexOf(o) >= 0;
1380 }
1381
1382 public boolean containsAll(Collection<?> c) {
1383 return list.internalContainsAll(c, offset, offset + size);
1384 }
1385
1386 public boolean equals(Object o) {
1387 if (o == this)
1388 return true;
1389 if (!(o instanceof List))
1390 return false;
1391 return list.internalEquals((List<?>)(o), offset, offset + size);
1392 }
1393
1394 public E get(int index) {
1395 if (index < 0 || index >= size)
1396 throw new ArrayIndexOutOfBoundsException(index);
1397 return list.get(index + offset);
1398 }
1399
1400 public int hashCode() {
1401 return list.internalHashCode(offset, offset + size);
1402 }
1403
1404 public int indexOf(Object o) {
1405 SequenceLock lock = list.lock;
1406 long seq = lock.awaitAvailability();
1407 Object[] items = list.array;
1408 int c = list.count;
1409 if (c <= items.length) {
1410 int idx = list.validatedIndexOf(o, items, offset,
1411 offset + size, seq);
1412 if (lock.getSequence() == seq)
1413 return idx < 0 ? -1 : idx - offset;
1414 }
1415 lock.lock();
1416 try {
1417 int idx = list.rawIndexOf(o, offset, offset + size);
1418 return idx < 0 ? -1 : idx - offset;
1419 } finally {
1420 lock.unlock();
1421 }
1422 }
1423
1424 public boolean isEmpty() {
1425 return size == 0;
1426 }
1427
1428 public Iterator<E> iterator() {
1429 return new SubItr<E>(this, offset);
1430 }
1431
1432 public int lastIndexOf(Object o) {
1433 SequenceLock lock = list.lock;
1434 long seq = lock.awaitAvailability();
1435 Object[] items = list.array;
1436 int c = list.count;
1437 if (c <= items.length) {
1438 int idx = list.validatedLastIndexOf(o, items, offset+size-1,
1439 offset, seq);
1440 if (lock.getSequence() == seq)
1441 return idx < 0 ? -1 : idx - offset;
1442 }
1443 lock.lock();
1444 try {
1445 int idx = list.rawLastIndexOf(o, offset + size - 1, offset);
1446 return idx < 0 ? -1 : idx - offset;
1447 } finally {
1448 lock.unlock();
1449 }
1450 }
1451
1452 public ListIterator<E> listIterator() {
1453 return new SubItr<E>(this, offset);
1454 }
1455
1456 public ListIterator<E> listIterator(int index) {
1457 return new SubItr<E>(this, index + offset);
1458 }
1459
1460 public E remove(int index) {
1461 Object result;
1462 SequenceLock lock = list.lock;
1463 lock.lock();
1464 try {
1465 Object[] items = list.array;
1466 int i = index + offset;
1467 if (index < 0 || index >= size || i >= items.length)
1468 throw new ArrayIndexOutOfBoundsException(index);
1469 result = items[i];
1470 list.rawRemoveAt(i);
1471 size--;
1472 } finally {
1473 lock.unlock();
1474 }
1475 return (E)result;
1476 }
1477
1478 public boolean remove(Object o) {
1479 boolean removed = false;
1480 SequenceLock lock = list.lock;
1481 lock.lock();
1482 try {
1483 if (list.rawRemoveAt(list.rawIndexOf(o, offset,
1484 offset + size))) {
1485 removed = true;
1486 --size;
1487 }
1488 } finally {
1489 lock.unlock();
1490 }
1491 return removed;
1492 }
1493
1494 public boolean removeAll(Collection<?> c) {
1495 return list.internalRemoveAll(c, offset, offset + size);
1496 }
1497
1498 public boolean retainAll(Collection<?> c) {
1499 return list.internalRetainAll(c, offset, offset + size);
1500 }
1501
1502 public E set(int index, E element) {
1503 if (index < 0 || index >= size)
1504 throw new ArrayIndexOutOfBoundsException(index);
1505 return list.set(index+offset, element);
1506 }
1507
1508 public int size() {
1509 return size;
1510 }
1511
1512 public List<E> subList(int fromIndex, int toIndex) {
1513 int c = size;
1514 int ssize = toIndex - fromIndex;
1515 if (fromIndex < 0 || toIndex > c || ssize < 0)
1516 throw new IndexOutOfBoundsException();
1517 return new ReadMostlyVectorSublist<E>(list, offset+fromIndex, ssize);
1518 }
1519
1520 public Object[] toArray() {
1521 return list.internalToArray(offset, offset + size);
1522 }
1523
1524 public <T> T[] toArray(T[] a) {
1525 return list.internalToArray(a, offset, offset + size);
1526 }
1527
1528 public String toString() {
1529 return list.internalToString(offset, offset + size);
1530 }
1531
1532 }
1533
1534 static final class SubItr<E> implements ListIterator<E> {
1535 final ReadMostlyVectorSublist<E> sublist;
1536 final ReadMostlyVector<E> list;
1537 final SequenceLock lock;
1538 Object[] items;
1539 Object next, prev;
1540 long seq;
1541 int cursor;
1542 int fence;
1543 int lastRet;
1544 boolean validNext, validPrev;
1545
1546 SubItr(ReadMostlyVectorSublist<E> sublist, int index) {
1547 this.sublist = sublist;
1548 this.list = sublist.list;
1549 this.lock = list.lock;
1550 this.cursor = index;
1551 this.lastRet = -1;
1552 refresh();
1553 if (index < 0 || index > fence)
1554 throw new ArrayIndexOutOfBoundsException(index);
1555 }
1556
1557 private void refresh() {
1558 validNext = validPrev = false;
1559 do {
1560 int n;
1561 seq = lock.awaitAvailability();
1562 items = list.array;
1563 if ((n = list.count) > items.length)
1564 continue;
1565 int b = sublist.offset + sublist.size;
1566 fence = b < n ? b : n;
1567 } while (lock.getSequence() != seq);
1568 }
1569
1570 public boolean hasNext() {
1571 boolean valid;
1572 int i = cursor;
1573 for (;;) {
1574 if (i >= fence || i < 0 || i >= items.length) {
1575 valid = false;
1576 break;
1577 }
1578 next = items[i];
1579 if (lock.getSequence() == seq) {
1580 valid = true;
1581 break;
1582 }
1583 refresh();
1584 }
1585 return validNext = valid;
1586 }
1587
1588 public boolean hasPrevious() {
1589 boolean valid;
1590 int i = cursor - 1;
1591 for (;;) {
1592 if (i >= fence || i < 0 || i >= items.length) {
1593 valid = false;
1594 break;
1595 }
1596 prev = items[i];
1597 if (lock.getSequence() == seq) {
1598 valid = true;
1599 break;
1600 }
1601 refresh();
1602 }
1603 return validPrev = valid;
1604 }
1605
1606 public E next() {
1607 if (validNext || hasNext()) {
1608 validNext = false;
1609 lastRet = cursor++;
1610 return (E) next;
1611 }
1612 throw new NoSuchElementException();
1613 }
1614
1615 public E previous() {
1616 if (validPrev || hasPrevious()) {
1617 validPrev = false;
1618 lastRet = cursor--;
1619 return (E) prev;
1620 }
1621 throw new NoSuchElementException();
1622 }
1623
1624 public int nextIndex() {
1625 return cursor - sublist.offset;
1626 }
1627
1628 public int previousIndex() {
1629 return cursor - 1 - sublist.offset;
1630 }
1631
1632 public void remove() {
1633 int i = lastRet;
1634 if (i < 0)
1635 throw new IllegalStateException();
1636 cursor = i;
1637 lastRet = -1;
1638 lock.lock();
1639 try {
1640 if (i < list.count) {
1641 list.remove(i);
1642 --sublist.size;
1643 }
1644 } finally {
1645 lock.unlock();
1646 }
1647 refresh();
1648 }
1649
1650 public void set(E e) {
1651 int i = lastRet;
1652 if (i < 0)
1653 throw new IllegalStateException();
1654 lock.lock();
1655 try {
1656 if (i < list.count)
1657 list.set(i, e);
1658 } finally {
1659 lock.unlock();
1660 }
1661 refresh();
1662 }
1663
1664 public void add(E e) {
1665 int i = cursor;
1666 if (i < 0)
1667 throw new IllegalStateException();
1668 cursor = i + 1;
1669 lastRet = -1;
1670 lock.lock();
1671 try {
1672 if (i <= list.count) {
1673 list.add(i, e);
1674 ++sublist.size;
1675 }
1676 } finally {
1677 lock.unlock();
1678 }
1679 refresh();
1680 }
1681
1682 }
1683 }
1684