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

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, count, 0);
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 n = count;
874 @SuppressWarnings("unchecked")
875 E e = (items.length > 0) ? (E) items[0] : null;
876 if (lock.getSequence() == seq) {
877 if (n <= 0)
878 throw new NoSuchElementException();
879 return e;
880 }
881 }
882 }
883
884 /** See {@link Vector#lastElement} */
885 public E lastElement() {
886 final SequenceLock lock = this.lock;
887 for (;;) {
888 long seq = lock.awaitAvailability();
889 Object[] items = array;
890 int n = count;
891 @SuppressWarnings("unchecked")
892 E e = (n > 0 && items.length >= n) ? (E) items[n - 1] : null;
893 if (lock.getSequence() == seq) {
894 if (n <= 0)
895 throw new NoSuchElementException();
896 return e;
897 }
898 }
899 }
900
901 /** See {@link Vector#indexOf(Object, int)} */
902 public int indexOf(Object o, int index) {
903 final SequenceLock lock = this.lock;
904 int idx = 0;
905 boolean ex = false;
906 long seq = lock.awaitAvailability();
907 Object[] items = array;
908 int n = count;
909 boolean retry = false;
910 if (n > items.length)
911 retry = true;
912 else if (index < 0)
913 ex = true;
914 else
915 idx = validatedIndexOf(o, items, index, n, seq);
916 if (retry || lock.getSequence() != seq) {
917 lock.lock();
918 try {
919 if (index < 0)
920 ex = true;
921 else
922 idx = rawIndexOf(o, index, count);
923 } finally {
924 lock.unlock();
925 }
926 }
927 if (ex)
928 throw new ArrayIndexOutOfBoundsException(index);
929 return idx;
930 }
931
932 /** See {@link Vector#lastIndexOf(Object, int)} */
933 public int lastIndexOf(Object o, int index) {
934 final SequenceLock lock = this.lock;
935 int idx = 0;
936 boolean ex = false;
937 long seq = lock.awaitAvailability();
938 Object[] items = array;
939 int n = count;
940 boolean retry = false;
941 if (n > items.length)
942 retry = true;
943 else if (index >= n)
944 ex = true;
945 else
946 idx = validatedLastIndexOf(o, items, index, 0, seq);
947 if (retry || lock.getSequence() != seq) {
948 lock.lock();
949 try {
950 if (index >= count)
951 ex = true;
952 else
953 idx = rawLastIndexOf(o, index, 0);
954 } finally {
955 lock.unlock();
956 }
957 }
958 if (ex)
959 throw new ArrayIndexOutOfBoundsException(index);
960 return idx;
961 }
962
963 /** See {@link Vector#setSize} */
964 public void setSize(int newSize) {
965 if (newSize < 0)
966 throw new ArrayIndexOutOfBoundsException(newSize);
967 final SequenceLock lock = this.lock;
968 lock.lock();
969 try {
970 int n = count;
971 if (newSize > n)
972 grow(newSize);
973 else {
974 Object[] items = array;
975 for (int i = newSize ; i < n ; i++)
976 items[i] = null;
977 }
978 count = newSize;
979 } finally {
980 lock.unlock();
981 }
982 }
983
984 /** See {@link Vector#copyInto} */
985 public void copyInto(Object[] anArray) {
986 final SequenceLock lock = this.lock;
987 lock.lock();
988 try {
989 System.arraycopy(array, 0, anArray, 0, count);
990 } finally {
991 lock.unlock();
992 }
993 }
994
995 /** See {@link Vector#trimToSize} */
996 public void trimToSize() {
997 final SequenceLock lock = this.lock;
998 lock.lock();
999 try {
1000 Object[] items = array;
1001 int n = count;
1002 if (n < items.length)
1003 array = Arrays.copyOf(items, n);
1004 } finally {
1005 lock.unlock();
1006 }
1007 }
1008
1009 /** See {@link Vector#ensureCapacity} */
1010 public void ensureCapacity(int minCapacity) {
1011 if (minCapacity > 0) {
1012 final SequenceLock lock = this.lock;
1013 lock.lock();
1014 try {
1015 if (minCapacity - array.length > 0)
1016 grow(minCapacity);
1017 } finally {
1018 lock.unlock();
1019 }
1020 }
1021 }
1022
1023 /** See {@link Vector#elements} */
1024 public Enumeration<E> elements() {
1025 return new Itr<E>(this, 0);
1026 }
1027
1028 /** See {@link Vector#capacity} */
1029 public int capacity() {
1030 return array.length;
1031 }
1032
1033 /** See {@link Vector#elementAt} */
1034 public E elementAt(int index) {
1035 return get(index);
1036 }
1037
1038 /** See {@link Vector#setElementAt} */
1039 public void setElementAt(E obj, int index) {
1040 set(index, obj);
1041 }
1042
1043 /** See {@link Vector#removeElementAt} */
1044 public void removeElementAt(int index) {
1045 remove(index);
1046 }
1047
1048 /** See {@link Vector#insertElementAt} */
1049 public void insertElementAt(E obj, int index) {
1050 add(index, obj);
1051 }
1052
1053 /** See {@link Vector#addElement} */
1054 public void addElement(E obj) {
1055 add(obj);
1056 }
1057
1058 /** See {@link Vector#removeElement} */
1059 public boolean removeElement(Object obj) {
1060 return remove(obj);
1061 }
1062
1063 /** See {@link Vector#removeAllElements} */
1064 public void removeAllElements() {
1065 clear();
1066 }
1067
1068 // other methods
1069
1070 public ReadMostlyVector<E> clone() {
1071 final SequenceLock lock = this.lock;
1072 Object[] a = null;
1073 boolean retry = false;
1074 long seq = lock.awaitAvailability();
1075 Object[] items = array;
1076 int n = count;
1077 if (n <= items.length)
1078 a = Arrays.copyOf(items, n);
1079 else
1080 retry = true;
1081 if (retry || lock.getSequence() != seq) {
1082 lock.lock();
1083 try {
1084 n = count;
1085 a = Arrays.copyOf(array, n);
1086 } finally {
1087 lock.unlock();
1088 }
1089 }
1090 return new ReadMostlyVector<E>(a, n, capacityIncrement);
1091 }
1092
1093 private void writeObject(java.io.ObjectOutputStream s)
1094 throws java.io.IOException {
1095 final SequenceLock lock = this.lock;
1096 lock.lock();
1097 try {
1098 s.defaultWriteObject();
1099 } finally {
1100 lock.unlock();
1101 }
1102 }
1103
1104 static final class Itr<E> implements ListIterator<E>, Enumeration<E> {
1105 final ReadMostlyVector<E> list;
1106 final SequenceLock lock;
1107 Object[] items;
1108 E next, prev;
1109 long seq;
1110 int cursor;
1111 int fence;
1112 int lastRet;
1113 boolean validNext, validPrev;
1114
1115 Itr(ReadMostlyVector<E> list, int index) {
1116 this.list = list;
1117 this.lock = list.lock;
1118 this.cursor = index;
1119 this.lastRet = -1;
1120 refresh();
1121 if (index < 0 || index > fence)
1122 throw new ArrayIndexOutOfBoundsException(index);
1123 }
1124
1125 private void refresh() {
1126 validNext = validPrev = false;
1127 do {
1128 seq = lock.awaitAvailability();
1129 items = list.array;
1130 } while ((fence = list.count) > items.length ||
1131 lock.getSequence() != seq);
1132 }
1133
1134 @SuppressWarnings("unchecked")
1135 public boolean hasNext() {
1136 boolean valid;
1137 int i = cursor;
1138 for (;;) {
1139 if (i >= fence || i < 0 || i >= items.length) {
1140 valid = false;
1141 break;
1142 }
1143 next = (E) items[i];
1144 if (lock.getSequence() == seq) {
1145 valid = true;
1146 break;
1147 }
1148 refresh();
1149 }
1150 return validNext = valid;
1151 }
1152
1153 @SuppressWarnings("unchecked")
1154 public boolean hasPrevious() {
1155 boolean valid;
1156 int i = cursor - 1;
1157 for (;;) {
1158 if (i >= fence || i < 0 || i >= items.length) {
1159 valid = false;
1160 break;
1161 }
1162 prev = (E) items[i];
1163 if (lock.getSequence() == seq) {
1164 valid = true;
1165 break;
1166 }
1167 refresh();
1168 }
1169 return validPrev = valid;
1170 }
1171
1172 public E next() {
1173 if (validNext || hasNext()) {
1174 validNext = false;
1175 lastRet = cursor++;
1176 return next;
1177 }
1178 throw new NoSuchElementException();
1179 }
1180
1181 public E previous() {
1182 if (validPrev || hasPrevious()) {
1183 validPrev = false;
1184 lastRet = cursor--;
1185 return prev;
1186 }
1187 throw new NoSuchElementException();
1188 }
1189
1190 public void remove() {
1191 int i = lastRet;
1192 if (i < 0)
1193 throw new IllegalStateException();
1194 lock.lock();
1195 try {
1196 if (i < list.count)
1197 list.remove(i);
1198 } finally {
1199 lock.unlock();
1200 }
1201 cursor = i;
1202 lastRet = -1;
1203 refresh();
1204 }
1205
1206 public void set(E e) {
1207 int i = lastRet;
1208 if (i < 0)
1209 throw new IllegalStateException();
1210 lock.lock();
1211 try {
1212 if (i < list.count)
1213 list.set(i, e);
1214 } finally {
1215 lock.unlock();
1216 }
1217 refresh();
1218 }
1219
1220 public void add(E e) {
1221 int i = cursor;
1222 if (i < 0)
1223 throw new IllegalStateException();
1224 lock.lock();
1225 try {
1226 if (i <= list.count)
1227 list.add(i, e);
1228 } finally {
1229 lock.unlock();
1230 }
1231 cursor = i + 1;
1232 lastRet = -1;
1233 refresh();
1234 }
1235
1236 public boolean hasMoreElements() { return hasNext(); }
1237 public E nextElement() { return next(); }
1238 public int nextIndex() { return cursor; }
1239 public int previousIndex() { return cursor - 1; }
1240 }
1241
1242 static final class ReadMostlyVectorSublist<E>
1243 implements List<E>, RandomAccess, java.io.Serializable {
1244 static final long serialVersionUID = 3041673470172026059L;
1245
1246 final ReadMostlyVector<E> list;
1247 final int offset;
1248 volatile int size;
1249
1250 ReadMostlyVectorSublist(ReadMostlyVector<E> list,
1251 int offset, int size) {
1252 this.list = list;
1253 this.offset = offset;
1254 this.size = size;
1255 }
1256
1257 private void rangeCheck(int index) {
1258 if (index < 0 || index >= size)
1259 throw new ArrayIndexOutOfBoundsException(index);
1260 }
1261
1262 public boolean add(E element) {
1263 final SequenceLock lock = list.lock;
1264 lock.lock();
1265 try {
1266 int c = size;
1267 list.rawAddAt(c + offset, element);
1268 size = c + 1;
1269 } finally {
1270 lock.unlock();
1271 }
1272 return true;
1273 }
1274
1275 public void add(int index, E element) {
1276 final SequenceLock lock = list.lock;
1277 lock.lock();
1278 try {
1279 if (index < 0 || index > size)
1280 throw new ArrayIndexOutOfBoundsException(index);
1281 list.rawAddAt(index + offset, element);
1282 ++size;
1283 } finally {
1284 lock.unlock();
1285 }
1286 }
1287
1288 public boolean addAll(Collection<? extends E> c) {
1289 Object[] elements = c.toArray();
1290 final SequenceLock lock = list.lock;
1291 lock.lock();
1292 try {
1293 int s = size;
1294 int pc = list.count;
1295 list.rawAddAllAt(offset + s, elements);
1296 int added = list.count - pc;
1297 size = s + added;
1298 return added != 0;
1299 } finally {
1300 lock.unlock();
1301 }
1302 }
1303
1304 public boolean addAll(int index, Collection<? extends E> c) {
1305 Object[] elements = c.toArray();
1306 final SequenceLock lock = list.lock;
1307 lock.lock();
1308 try {
1309 int s = size;
1310 if (index < 0 || index > s)
1311 throw new ArrayIndexOutOfBoundsException(index);
1312 int pc = list.count;
1313 list.rawAddAllAt(index + offset, elements);
1314 int added = list.count - pc;
1315 size = s + added;
1316 return added != 0;
1317 } finally {
1318 lock.unlock();
1319 }
1320 }
1321
1322 public void clear() {
1323 final SequenceLock lock = list.lock;
1324 lock.lock();
1325 try {
1326 list.internalClear(offset, offset + size);
1327 size = 0;
1328 } finally {
1329 lock.unlock();
1330 }
1331 }
1332
1333 public boolean contains(Object o) {
1334 return indexOf(o) >= 0;
1335 }
1336
1337 public boolean containsAll(Collection<?> c) {
1338 return list.internalContainsAll(c, offset, offset + size);
1339 }
1340
1341 public boolean equals(Object o) {
1342 if (o == this)
1343 return true;
1344 if (!(o instanceof List))
1345 return false;
1346 return list.internalEquals((List<?>)(o), offset, offset + size);
1347 }
1348
1349 public E get(int index) {
1350 if (index < 0 || index >= size)
1351 throw new ArrayIndexOutOfBoundsException(index);
1352 return list.get(index + offset);
1353 }
1354
1355 public int hashCode() {
1356 return list.internalHashCode(offset, offset + size);
1357 }
1358
1359 public int indexOf(Object o) {
1360 final SequenceLock lock = list.lock;
1361 long seq = lock.awaitAvailability();
1362 Object[] items = list.array;
1363 int c = list.count;
1364 if (c <= items.length) {
1365 int idx = list.validatedIndexOf(o, items, offset,
1366 offset + size, seq);
1367 if (lock.getSequence() == seq)
1368 return idx < 0 ? -1 : idx - offset;
1369 }
1370 lock.lock();
1371 try {
1372 int idx = list.rawIndexOf(o, offset, offset + size);
1373 return idx < 0 ? -1 : idx - offset;
1374 } finally {
1375 lock.unlock();
1376 }
1377 }
1378
1379 public boolean isEmpty() {
1380 return size == 0;
1381 }
1382
1383 public Iterator<E> iterator() {
1384 return new SubItr<E>(this, offset);
1385 }
1386
1387 public int lastIndexOf(Object o) {
1388 final SequenceLock lock = list.lock;
1389 long seq = lock.awaitAvailability();
1390 Object[] items = list.array;
1391 int c = list.count;
1392 if (c <= items.length) {
1393 int idx = list.validatedLastIndexOf(o, items, offset+size-1,
1394 offset, seq);
1395 if (lock.getSequence() == seq)
1396 return idx < 0 ? -1 : idx - offset;
1397 }
1398 lock.lock();
1399 try {
1400 int idx = list.rawLastIndexOf(o, offset + size - 1, offset);
1401 return idx < 0 ? -1 : idx - offset;
1402 } finally {
1403 lock.unlock();
1404 }
1405 }
1406
1407 public ListIterator<E> listIterator() {
1408 return new SubItr<E>(this, offset);
1409 }
1410
1411 public ListIterator<E> listIterator(int index) {
1412 return new SubItr<E>(this, index + offset);
1413 }
1414
1415 public E remove(int index) {
1416 final SequenceLock lock = list.lock;
1417 lock.lock();
1418 try {
1419 Object[] items = list.array;
1420 int i = index + offset;
1421 if (index < 0 || index >= size || i >= items.length)
1422 throw new ArrayIndexOutOfBoundsException(index);
1423 @SuppressWarnings("unchecked")
1424 E result = (E) items[i];
1425 list.rawRemoveAt(i);
1426 size--;
1427 return result;
1428 } finally {
1429 lock.unlock();
1430 }
1431 }
1432
1433 public boolean remove(Object o) {
1434 final SequenceLock lock = list.lock;
1435 lock.lock();
1436 try {
1437 if (list.rawRemoveAt(list.rawIndexOf(o, offset,
1438 offset + size))) {
1439 --size;
1440 return true;
1441 }
1442 else
1443 return false;
1444 } finally {
1445 lock.unlock();
1446 }
1447 }
1448
1449 public boolean removeAll(Collection<?> c) {
1450 return list.internalRemoveAll(c, offset, offset + size);
1451 }
1452
1453 public boolean retainAll(Collection<?> c) {
1454 return list.internalRetainAll(c, offset, offset + size);
1455 }
1456
1457 public E set(int index, E element) {
1458 if (index < 0 || index >= size)
1459 throw new ArrayIndexOutOfBoundsException(index);
1460 return list.set(index+offset, element);
1461 }
1462
1463 public int size() {
1464 return size;
1465 }
1466
1467 public List<E> subList(int fromIndex, int toIndex) {
1468 int c = size;
1469 int ssize = toIndex - fromIndex;
1470 if (fromIndex < 0 || toIndex > c || ssize < 0)
1471 throw new IndexOutOfBoundsException();
1472 return new ReadMostlyVectorSublist<E>(list, offset+fromIndex, ssize);
1473 }
1474
1475 public Object[] toArray() {
1476 return list.internalToArray(offset, offset + size);
1477 }
1478
1479 public <T> T[] toArray(T[] a) {
1480 return list.internalToArray(a, offset, offset + size);
1481 }
1482
1483 public String toString() {
1484 return list.internalToString(offset, offset + size);
1485 }
1486
1487 }
1488
1489 static final class SubItr<E> implements ListIterator<E> {
1490 final ReadMostlyVectorSublist<E> sublist;
1491 final ReadMostlyVector<E> list;
1492 final SequenceLock lock;
1493 Object[] items;
1494 E next, prev;
1495 long seq;
1496 int cursor;
1497 int fence;
1498 int lastRet;
1499 boolean validNext, validPrev;
1500
1501 SubItr(ReadMostlyVectorSublist<E> sublist, int index) {
1502 this.sublist = sublist;
1503 this.list = sublist.list;
1504 this.lock = list.lock;
1505 this.cursor = index;
1506 this.lastRet = -1;
1507 refresh();
1508 if (index < 0 || index > fence)
1509 throw new ArrayIndexOutOfBoundsException(index);
1510 }
1511
1512 private void refresh() {
1513 validNext = validPrev = false;
1514 do {
1515 int n;
1516 seq = lock.awaitAvailability();
1517 items = list.array;
1518 if ((n = list.count) > items.length)
1519 continue;
1520 int b = sublist.offset + sublist.size;
1521 fence = b < n ? b : n;
1522 } while (lock.getSequence() != seq);
1523 }
1524
1525 @SuppressWarnings("unchecked")
1526 public boolean hasNext() {
1527 boolean valid;
1528 int i = cursor;
1529 for (;;) {
1530 if (i >= fence || i < 0 || i >= items.length) {
1531 valid = false;
1532 break;
1533 }
1534 next = (E) items[i];
1535 if (lock.getSequence() == seq) {
1536 valid = true;
1537 break;
1538 }
1539 refresh();
1540 }
1541 return validNext = valid;
1542 }
1543
1544 @SuppressWarnings("unchecked")
1545 public boolean hasPrevious() {
1546 boolean valid;
1547 int i = cursor - 1;
1548 for (;;) {
1549 if (i >= fence || i < 0 || i >= items.length) {
1550 valid = false;
1551 break;
1552 }
1553 prev = (E) items[i];
1554 if (lock.getSequence() == seq) {
1555 valid = true;
1556 break;
1557 }
1558 refresh();
1559 }
1560 return validPrev = valid;
1561 }
1562
1563 public E next() {
1564 if (validNext || hasNext()) {
1565 validNext = false;
1566 lastRet = cursor++;
1567 return next;
1568 }
1569 throw new NoSuchElementException();
1570 }
1571
1572 public E previous() {
1573 if (validPrev || hasPrevious()) {
1574 validPrev = false;
1575 lastRet = cursor--;
1576 return prev;
1577 }
1578 throw new NoSuchElementException();
1579 }
1580
1581 public int nextIndex() {
1582 return cursor - sublist.offset;
1583 }
1584
1585 public int previousIndex() {
1586 return cursor - 1 - sublist.offset;
1587 }
1588
1589 public void remove() {
1590 int i = lastRet;
1591 if (i < 0)
1592 throw new IllegalStateException();
1593 cursor = i;
1594 lastRet = -1;
1595 lock.lock();
1596 try {
1597 if (i < list.count) {
1598 list.remove(i);
1599 --sublist.size;
1600 }
1601 } finally {
1602 lock.unlock();
1603 }
1604 refresh();
1605 }
1606
1607 public void set(E e) {
1608 int i = lastRet;
1609 if (i < 0)
1610 throw new IllegalStateException();
1611 lock.lock();
1612 try {
1613 if (i < list.count)
1614 list.set(i, e);
1615 } finally {
1616 lock.unlock();
1617 }
1618 refresh();
1619 }
1620
1621 public void add(E e) {
1622 int i = cursor;
1623 if (i < 0)
1624 throw new IllegalStateException();
1625 cursor = i + 1;
1626 lastRet = -1;
1627 lock.lock();
1628 try {
1629 if (i <= list.count) {
1630 list.add(i, e);
1631 ++sublist.size;
1632 }
1633 } finally {
1634 lock.unlock();
1635 }
1636 refresh();
1637 }
1638
1639 }
1640 }
1641