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