ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.35
Committed: Sun Jan 18 20:17:33 2015 UTC (9 years, 4 months ago) by jsr166
Branch: MAIN
CVS Tags: HEAD
Changes since 1.34: +1 -0 lines
Log Message:
exactly one blank line before and after package statements

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