ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
Revision: 1.1
Committed: Fri Jul 15 23:56:18 2011 UTC (12 years, 11 months ago) by dl
Branch: MAIN
Log Message:
Initial check-in

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