ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.34
Committed: Mon Jan 14 18:52:56 2013 UTC (11 years, 4 months ago) by jsr166
Branch: MAIN
Changes since 1.33: +1 -1 lines
Log Message:
remove javac [cast] warning

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