ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.6
Committed: Sun Jul 17 17:17:46 2011 UTC (12 years, 10 months ago) by jsr166
Branch: MAIN
Changes since 1.5: +6 -6 lines
Log Message:
coding style

File Contents

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