ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.7
Committed: Mon Jul 18 14:44:32 2011 UTC (12 years, 10 months ago) by dl
Branch: MAIN
Changes since 1.6: +37 -34 lines
Log Message:
Minor improvements

File Contents

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