ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.22
Committed: Sat Dec 31 21:16:14 2011 UTC (12 years, 5 months ago) by jsr166
Branch: MAIN
Changes since 1.21: +1 -1 lines
Log Message:
bug fix for lastIndexOf(Object) - second try

File Contents

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