ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.3
Committed: Sat Jul 16 14:56:30 2011 UTC (12 years, 11 months ago) by jsr166
Branch: MAIN
Changes since 1.2: +11 -11 lines
Log Message:
whitespace

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