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