ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/extra/ReadMostlyVector.java
(Generate patch)

Comparing jsr166/src/jsr166e/extra/ReadMostlyVector.java (file contents):
Revision 1.9 by jsr166, Tue Jul 19 12:05:09 2011 UTC vs.
Revision 1.33 by jsr166, Wed Jan 2 04:35:20 2013 UTC

# Line 5 | Line 5
5   */
6  
7   package jsr166e.extra;
8 < import jsr166e.*;
8 > import jsr166e.StampedLock;
9   import java.util.*;
10  
11   /**
# Line 14 | Line 14 | import java.util.*;
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()
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,
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}.
# Line 32 | Line 32 | import java.util.*;
32   *
33   * @author Doug Lea
34   */
35 < public class ReadMostlyVector<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
35 > public class ReadMostlyVector<E>
36 >        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
37      private static final long serialVersionUID = 8673264195747942595L;
38  
39      /*
# Line 48 | Line 49 | public class ReadMostlyVector<E> impleme
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      /**
# Line 56 | Line 62 | public class ReadMostlyVector<E> impleme
62       */
63      private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
64  
65 <    // fields are non-private to simpify nested class access
65 >    // fields are non-private to simplify nested class access
66      Object[] array;
67 <    final SequenceLock lock;
67 >    final StampedLock lock;
68      int count;
69      final int capacityIncrement;
70  
# Line 80 | Line 86 | public class ReadMostlyVector<E> impleme
86                                                 initialCapacity);
87          this.array = new Object[initialCapacity];
88          this.capacityIncrement = capacityIncrement;
89 <        this.lock = new SequenceLock();
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
90     *
96       * @throws IllegalArgumentException if initial capacity is negative
97       */
98      public ReadMostlyVector(int initialCapacity) {
# Line 95 | Line 100 | public class ReadMostlyVector<E> impleme
100      }
101  
102      /**
103 <     * Creates an empty vector with an underlying array of size {@code 10}.
103 >     * Creates an empty vector.
104       */
105      public ReadMostlyVector() {
106 <        this(10, 0);
106 >        this.capacityIncrement = 0;
107 >        this.lock = new StampedLock();
108      }
109  
110      /**
# Line 117 | Line 123 | public class ReadMostlyVector<E> impleme
123          this.array = elements;
124          this.count = elements.length;
125          this.capacityIncrement = 0;
126 <        this.lock = new SequenceLock();
126 >        this.lock = new StampedLock();
127      }
128  
129      // internal constructor for clone
# Line 125 | Line 131 | public class ReadMostlyVector<E> impleme
131          this.array = array;
132          this.count = count;
133          this.capacityIncrement = capacityIncrement;
134 <        this.lock = new SequenceLock();
134 >        this.lock = new StampedLock();
135      }
136  
137 +    static final int INITIAL_CAP = 16;
138 +
139      // For explanation, see CopyOnWriteArrayList
140 <    final void grow(int minCapacity) {
141 <        int oldCapacity = array.length;
142 <        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
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 <            newCapacity = hugeCapacity(minCapacity);
154 <        array = Arrays.copyOf(array, newCapacity);
155 <    }
156 <
157 <    static int hugeCapacity(int minCapacity) {
158 <        if (minCapacity < 0) // overflow
159 <            throw new OutOfMemoryError();
160 <        return (minCapacity > MAX_ARRAY_SIZE) ?
161 <            Integer.MAX_VALUE :
162 <            MAX_ARRAY_SIZE;
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      /*
# Line 154 | Line 168 | public class ReadMostlyVector<E> impleme
168       * as well as sublist and iterator classes.
169       */
170  
171 <    // Version of indexOf that returns -1 if either not present or invalid
172 <    final int validatedIndexOf(Object x, Object[] items, int index, int fence,
173 <                               long seq) {
174 <        for (int i = index; i < fence; ++i) {
175 <            Object e = items[i];
176 <            if (lock.getSequence() != seq)
177 <                break;
178 <            if ((x == null) ? e == null : x.equals(e))
179 <                return i;
180 <        }
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;
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 <    final int rawLastIndexOf(Object x, int index, int origin) {
186 <        Object[] items = array;
187 <        for (int i = index; i >= origin; --i) {
188 <            Object e = items[i];
189 <            if ((x == null) ? e == null : x.equals(e))
190 <                return i;
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(Object e) {
199 >    final void rawAdd(E e) {
200          int n = count;
201 <        if (n >= array.length)
202 <            grow(n + 1);
203 <        array[n] = e;
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, Object e) {
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 (n >= array.length)
214 <            grow(n + 1);
213 >        if (items == null || n >= items.length)
214 >            items = grow(n + 1);
215          if (index < n)
216 <            System.arraycopy(array, index, array, index + 1, n - index);
217 <        array[index] = e;
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 (newCount >= array.length)
231 <            grow(newCount);
232 <        int mv = count - index;
230 >        if (items == null || newCount >= items.length)
231 >            items = grow(newCount);
232 >        int mv = n - index;
233          if (mv > 0)
234 <            System.arraycopy(array, index, array, index + len, mv);
235 <        System.arraycopy(elements, 0, array, index, len);
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 <        if (index < 0 || index > n)
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(array, index + 1, array, index, mv);
248 <        array[n] = null;
247 >            System.arraycopy(items, index + 1, items, index, mv);
248 >        items[n] = null;
249          count = n;
250          return true;
251      }
# Line 256 | Line 257 | public class ReadMostlyVector<E> impleme
257       * is left negative if the bound should be determined via count
258       * field under lock.
259       */
260 <    final boolean internalRemoveAll(Collection<?> c, int origin, int bound) {
260 <        SequenceLock lock = this.lock;
260 >    final boolean lockedRemoveAll(Collection<?> c, int origin, int bound) {
261          boolean removed = false;
262 <        lock.lock();
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(rawIndexOf(x, origin, fence)))
269 >                    while (rawRemoveAt(findFirstIndex(array, x, origin, fence)))
270                          removed = true;
271                  }
272              }
273          } finally {
274 <            lock.unlock();
274 >            lock.unlockWrite(stamp);
275          }
276          return removed;
277      }
278  
279 <    final boolean internalRetainAll(Collection<?> c, int origin, int bound) {
280 <        SequenceLock lock = this.lock;
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 <            lock.lock();
283 >            long stamp = lock.writeLock();
284              try {
285 <                int i = origin;
286 <                int n = count;
287 <                int fence = bound < 0 || bound > n ? n : bound;
288 <                while (i >= 0 && i < fence) {
289 <                    if (c.contains(array[i]))
290 <                        ++i;
291 <                    else {
292 <                        --fence;
293 <                        int mv = --count - i;
294 <                        if (mv > 0)
295 <                            System.arraycopy(array, i + 1, array, i, mv);
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.unlock();
306 >                lock.unlockWrite(stamp);
307              }
308          }
309          return removed;
310      }
311  
312      final void internalClear(int origin, int bound) {
313 <        int n = count;
314 <        int fence = bound < 0 || bound > n ? n : bound;
315 <        if (origin >= 0 && origin < fence) {
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(array, origin + removed, array, origin, mv);
325 >                System.arraycopy(items, origin + removed, items, origin, mv);
326              for (int i = n; i < newCount; ++i)
327 <                array[i] = null;
327 >                items[i] = null;
328              count = newCount;
329          }
330      }
331  
332      final boolean internalContainsAll(Collection<?> c, int origin, int bound) {
333 <        SequenceLock lock = this.lock;
334 <        boolean contained;
335 <        boolean locked = false;
336 <        try {
337 <            for (;;) {
338 <                long seq = lock.awaitAvailability();
339 <                Object[] items = array;
340 <                int len = items.length;
341 <                int n = count;
342 <                if (n > len)
343 <                    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;
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              }
353        } finally {
354            if (locked)
355                lock.unlock();
345          }
346 <        return contained;
346 >        else if (!c.isEmpty())
347 >            return false;
348 >        return true;
349      }
350  
351      final boolean internalEquals(List<?> list, int origin, int bound) {
352 <        SequenceLock lock = this.lock;
353 <        boolean locked = false;
354 <        boolean equal;
355 <        try {
356 <            for (;;) {
357 <                long seq = lock.awaitAvailability();
358 <                Object[] items = array;
359 <                int n = count;
360 <                if (n > items.length || origin < 0)
361 <                    equal = false;
362 <                else {
363 <                    equal = true;
364 <                    int fence = bound < 0 || bound > n ? n : bound;
365 <                    Iterator<?> it = list.iterator();
366 <                    for (int i = origin; i < fence; ++i) {
367 <                        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;
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 <        } finally {
370 <            if (locked)
396 <                lock.unlock();
369 >            if (it.hasNext())
370 >                return false;
371          }
372 <        return equal;
372 >        else if (!list.isEmpty())
373 >            return false;
374 >        return true;
375      }
376  
377      final int internalHashCode(int origin, int bound) {
378 <        SequenceLock lock = this.lock;
379 <        int hash;
380 <        boolean locked = false;
381 <        try {
382 <            for (;;) {
383 <                hash = 1;
384 <                long seq = lock.awaitAvailability();
385 <                Object[] items = array;
386 <                int len = items.length;
387 <                int n = count;
388 <                if (n > len)
389 <                    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;
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              }
426        } finally {
427            if (locked)
428                lock.unlock();
391          }
392          return hash;
393      }
394  
395      final String internalToString(int origin, int bound) {
396 <        SequenceLock lock = this.lock;
397 <        String ret;
398 <        boolean locked = false;
399 <        try {
400 <            outer:for (;;) {
401 <                long seq = lock.awaitAvailability();
402 <                Object[] items = array;
403 <                int len = items.length;
404 <                int n = count;
405 <                if (n > len)
406 <                    continue;
407 <                int fence = bound < 0 || bound > n ? n : bound;
408 <                if (origin < 0 || origin == fence)
409 <                    ret = "[]";
410 <                else {
411 <                    StringBuilder sb = new StringBuilder();
412 <                    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 <                    }
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                  }
467                if (lock.getSequence() == seq)
468                    break;
469                lock.lock();
470                locked = true;
414              }
472        } finally {
473            if (locked)
474                lock.unlock();
415          }
416 <        return ret;
416 >        return "[]";
417      }
418  
419      final Object[] internalToArray(int origin, int bound) {
420 <        Object[] result;
421 <        SequenceLock lock = this.lock;
422 <        boolean locked = false;
423 <        try {
424 <            for (;;) {
425 <                result = null;
426 <                long seq = lock.awaitAvailability();
427 <                Object[] items = array;
428 <                int len = items.length;
429 <                int n = count;
430 <                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();
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 result;
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 <        T[] result;
439 <        SequenceLock lock = this.lock;
440 <        boolean locked = false;
441 <        try {
442 <            for (;;) {
443 <                long seq = lock.awaitAvailability();
444 <                Object[] items = array;
445 <                int len = items.length;
446 <                int n = count;
447 <                if (n > len)
448 <                    continue;
449 <                int fence = bound < 0 || bound > n ? n : bound;
450 <                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);
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 <                    result = a;
453 >                    return a;
454                  }
455 <                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;
455 >                return (T[]) Arrays.copyOfRange(items, i, fence, a.getClass());
456              }
540        } finally {
541            if (locked)
542                lock.unlock();
457          }
458 <        return result;
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 <        SequenceLock lock = this.lock;
467 <        lock.lock();
466 >        final StampedLock lock = this.lock;
467 >        long stamp = lock.writeLock();
468          try {
469              rawAdd(e);
470          } finally {
471 <            lock.unlock();
471 >            lock.unlockWrite(stamp);
472          }
473          return true;
474      }
475  
476      public void add(int index, E element) {
477 <        SequenceLock lock = this.lock;
478 <        lock.lock();
477 >        final StampedLock lock = this.lock;
478 >        long stamp = lock.writeLock();
479          try {
480              rawAddAt(index, element);
481          } finally {
482 <            lock.unlock();
482 >            lock.unlockWrite(stamp);
483          }
484      }
485  
# Line 572 | Line 488 | public class ReadMostlyVector<E> impleme
488          int len = elements.length;
489          if (len == 0)
490              return false;
491 <        SequenceLock lock = this.lock;
492 <        lock.lock();
491 >        final StampedLock lock = this.lock;
492 >        long stamp = lock.writeLock();
493          try {
494 <            int newCount = count + len;
495 <            if (newCount >= array.length)
496 <                grow(newCount);
497 <            System.arraycopy(elements, 0, array, count, len);
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.unlock();
502 >            lock.unlockWrite(stamp);
503          }
504          return true;
505      }
506  
507      public boolean addAll(int index, Collection<? extends E> c) {
590        SequenceLock lock = this.lock;
591        boolean ret;
508          Object[] elements = c.toArray();
509 <        lock.lock();
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.unlock();
515 >            lock.unlockWrite(stamp);
516          }
517          return ret;
518      }
519  
520      public void clear() {
521 <        SequenceLock lock = this.lock;
522 <        lock.lock();
521 >        final StampedLock lock = this.lock;
522 >        long stamp = lock.writeLock();
523          try {
524 <            for (int i = 0; i < count; i++)
525 <                array[i] = null;
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.unlock();
532 >            lock.unlockWrite(stamp);
533          }
534      }
535  
# Line 616 | Line 538 | public class ReadMostlyVector<E> impleme
538      }
539  
540      public boolean containsAll(Collection<?> c) {
541 <        return internalContainsAll(c, 0, -1);
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) {
# Line 624 | Line 554 | public class ReadMostlyVector<E> impleme
554              return true;
555          if (!(o instanceof List))
556              return false;
557 <        return internalEquals((List<?>)o, 0, -1);
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 <        SequenceLock lock = this.lock;
568 <        for (;;) {
569 <            long seq = lock.awaitAvailability();
570 <            Object[] items = array;
571 <            int n = count;
572 <            if (n > items.length)
573 <                continue;
574 <            Object e; boolean ex;
575 <            if (index < 0 || index >= n) {
576 <                e = null;
577 <                ex = true;
578 <            }
579 <            else {
580 <                e = items[index];
581 <                ex = false;
582 <            }
583 <            if (lock.getSequence() == seq) {
584 <                if (ex)
585 <                    throw new ArrayIndexOutOfBoundsException(index);
586 <                else
587 <                    return (E)e;
588 <            }
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)e;
597      }
598  
599      public int hashCode() {
600 <        return internalHashCode(0, -1);
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 <        SequenceLock lock = this.lock;
613 <        for (;;) {
614 <            long seq = lock.awaitAvailability();
615 <            Object[] items = array;
616 <            int n = count;
617 <            if (n <= items.length) {
618 <                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 <            }
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 <        long ignore = lock.getSequence();
625 <        return count == 0;
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(this, 0);
630 >        return new Itr<E>(this, 0);
631      }
632  
633      public int lastIndexOf(Object o) {
634 <        SequenceLock lock = this.lock;
635 <        for (;;) {
636 <            long seq = lock.awaitAvailability();
637 <            Object[] items = array;
638 <            int n = count;
639 <            if (n <= items.length) {
640 <                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 <            }
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(this, 0);
646 >        return new Itr<E>(this, 0);
647      }
648  
649      public ListIterator<E> listIterator(int index) {
650 <        return new Itr(this, index);
650 >        return new Itr<E>(this, index);
651      }
652  
653 <    public E remove(int index) {
654 <        SequenceLock lock = this.lock;
655 <        Object oldValue;
656 <        lock.lock();
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 <                throw new ArrayIndexOutOfBoundsException(index);
661 <            oldValue = array[index];
662 <            rawRemoveAt(index);
660 >                oobe = true;
661 >            else {
662 >                oldValue = (E) array[index];
663 >                rawRemoveAt(index);
664 >            }
665          } finally {
666 <            lock.unlock();
666 >            lock.unlockWrite(stamp);
667          }
668 <        return (E)oldValue;
668 >        if (oobe)
669 >            throw new ArrayIndexOutOfBoundsException(index);
670 >        return oldValue;
671      }
672  
673      public boolean remove(Object o) {
674 <        SequenceLock lock = this.lock;
675 <        boolean removed;
745 <        lock.lock();
674 >        final StampedLock lock = this.lock;
675 >        long stamp = lock.writeLock();
676          try {
677 <            removed = rawRemoveAt(rawIndexOf(o, 0, count));
677 >            return rawRemoveAt(findFirstIndex(array, o, 0, count));
678          } finally {
679 <            lock.unlock();
679 >            lock.unlockWrite(stamp);
680          }
751        return removed;
681      }
682  
683      public boolean removeAll(Collection<?> c) {
684 <        return internalRemoveAll(c, 0, -1);
684 >        return lockedRemoveAll(c, 0, -1);
685      }
686  
687      public boolean retainAll(Collection<?> c) {
688 <        return internalRetainAll(c, 0, -1);
688 >        return lockedRetainAll(c, 0, -1);
689      }
690  
691 <    public E set(int index, E element) {
692 <        Object oldValue;
693 <        SequenceLock lock = this.lock;
694 <        lock.lock();
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 <            if (index < 0 || index >= count)
698 <                throw new ArrayIndexOutOfBoundsException(index);
699 <            oldValue = array[index];
700 <            array[index] = element;
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.unlock();
705 >            lock.unlockWrite(stamp);
706          }
707 <        return (E)oldValue;
707 >        if (oobe)
708 >            throw new ArrayIndexOutOfBoundsException(index);
709 >        return oldValue;
710      }
711  
712      public int size() {
713 <        long ignore = lock.getSequence();
714 <        return count;
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) {
783        int c = size();
731          int ssize = toIndex - fromIndex;
732 <        if (fromIndex < 0 || toIndex > c || ssize < 0)
733 <            throw new IndexOutOfBoundsException();
734 <        return new ReadMostlyVectorSublist(this, fromIndex, ssize);
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 <        return internalToArray(0, -1);
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 <        return internalToArray(a, 0, -1);
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 <        return internalToString(0, -1);
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 <     * Append the element if not present.
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 added;
789 <        SequenceLock lock = this.lock;
790 <        lock.lock();
788 >        boolean ret;
789 >        final StampedLock lock = this.lock;
790 >        long stamp = lock.writeLock();
791          try {
792 <            if (rawIndexOf(e, 0, count) < 0) {
792 >            if (findFirstIndex(array, e, 0, count) < 0) {
793                  rawAdd(e);
794 <                added = true;
794 >                ret = true;
795              }
796              else
797 <                added = false;
797 >                ret = false;
798          } finally {
799 <            lock.unlock();
799 >            lock.unlockWrite(stamp);
800          }
801 <        return added;
801 >        return ret;
802      }
803  
804      /**
# Line 840 | Line 817 | public class ReadMostlyVector<E> impleme
817          Object[] cs = c.toArray();
818          int clen = cs.length;
819          if (clen != 0) {
820 <            lock.lock();
820 >            long stamp = lock.writeLock();
821              try {
822                  for (int i = 0; i < clen; ++i) {
823 <                    Object e = cs[i];
824 <                    if (rawIndexOf(e, 0, count) < 0) {
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.unlock();
831 >                lock.unlockWrite(stamp);
832              }
833          }
834          return added;
# Line 869 | Line 847 | public class ReadMostlyVector<E> impleme
847      }
848  
849      static final class SnapshotIterator<E> implements Iterator<E> {
850 <        final Object[] items;
851 <        int cursor;
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 <        public E next() {
854 >        @SuppressWarnings("unchecked") public E next() {
855              if (cursor < items.length)
856                  return (E) items[cursor++];
857              throw new NoSuchElementException();
# Line 881 | Line 859 | public class ReadMostlyVector<E> impleme
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 <        SequenceLock lock = this.lock;
888 <        for (;;) {
889 <            long seq = lock.awaitAvailability();
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 <            int len = items.length;
893 <            int n = count;
894 <            if (n > len)
895 <                continue;
896 <            Object e; boolean ex;
897 <            if (n > 0) {
905 >            if (items != null && count > 0 && items.length > 0)
906                  e = items[0];
907 <                ex = false;
908 <            }
909 <            else {
910 <                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 <            }
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 <        SequenceLock lock = this.lock;
920 <        for (;;) {
921 <            long seq = lock.awaitAvailability();
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 len = items.length;
940 <            int n = count;
941 <            if (n > len)
942 <                continue;
943 <            Object e; boolean ex;
944 <            if (n > 0) {
945 <                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 >            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 <        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)
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 <        SequenceLock lock = this.lock;
970 <        int idx = 0;
971 <        boolean ex = false;
972 <        long seq = lock.awaitAvailability();
973 <        Object[] items = array;
974 <        int n = count;
975 <        boolean retry = false;
976 <        if (n > items.length)
977 <            retry = true;
978 <        else if (index >= n)
979 <            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 <            }
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 (ex)
981 >        if (oobe)
982              throw new ArrayIndexOutOfBoundsException(index);
983          return idx;
984      }
# Line 1005 | Line 987 | public class ReadMostlyVector<E> impleme
987      public void setSize(int newSize) {
988          if (newSize < 0)
989              throw new ArrayIndexOutOfBoundsException(newSize);
990 <        SequenceLock lock = this.lock;
991 <        lock.lock();
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 {
997 >            else if ((items = array) != null) {
998                  for (int i = newSize ; i < n ; i++)
999 <                    array[i] = null;
999 >                    items[i] = null;
1000              }
1001              count = newSize;
1002          } finally {
1003 <            lock.unlock();
1003 >            lock.unlockWrite(stamp);
1004          }
1005      }
1006  
1007      /** See {@link Vector#copyInto} */
1008      public void copyInto(Object[] anArray) {
1009 <        SequenceLock lock = this.lock;
1010 <        lock.lock();
1009 >        final StampedLock lock = this.lock;
1010 >        long stamp = lock.writeLock();
1011          try {
1012 <            System.arraycopy(array, 0, anArray, 0, count);
1012 >            Object[] items;
1013 >            if ((items = array) != null)
1014 >                System.arraycopy(items, 0, anArray, 0, count);
1015          } finally {
1016 <            lock.unlock();
1016 >            lock.unlockWrite(stamp);
1017          }
1018      }
1019  
1020      /** See {@link Vector#trimToSize} */
1021      public void trimToSize() {
1022 <        SequenceLock lock = this.lock;
1023 <        lock.lock();
1022 >        final StampedLock lock = this.lock;
1023 >        long stamp = lock.writeLock();
1024          try {
1025 <            if (count < array.length)
1026 <                array = Arrays.copyOf(array, count);
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.unlock();
1030 >            lock.unlockWrite(stamp);
1031          }
1032      }
1033  
1034      /** See {@link Vector#ensureCapacity} */
1035      public void ensureCapacity(int minCapacity) {
1036          if (minCapacity > 0) {
1037 <            SequenceLock lock = this.lock;
1038 <            lock.lock();
1037 >            final StampedLock lock = this.lock;
1038 >            long stamp = lock.writeLock();
1039              try {
1040 <                if (minCapacity - array.length > 0)
1040 >                Object[] items = array;
1041 >                int cap = (items == null) ? 0 : items.length;
1042 >                if (minCapacity - cap > 0)
1043                      grow(minCapacity);
1044              } finally {
1045 <                lock.unlock();
1045 >                lock.unlockWrite(stamp);
1046              }
1047          }
1048      }
1049  
1050      /** See {@link Vector#elements} */
1051      public Enumeration<E> elements() {
1052 <        return new Itr(this, 0);
1052 >        return new Itr<E>(this, 0);
1053      }
1054  
1055      /** See {@link Vector#capacity} */
1056      public int capacity() {
1068        long ignore = lock.getSequence();
1057          return array.length;
1058      }
1059  
# Line 1106 | Line 1094 | public class ReadMostlyVector<E> impleme
1094  
1095      // other methods
1096  
1097 <    public Object clone() {
1110 <        SequenceLock lock = this.lock;
1097 >    public ReadMostlyVector<E> clone() {
1098          Object[] a = null;
1099 <        boolean retry = false;
1100 <        long seq = lock.awaitAvailability();
1101 <        Object[] items = array;
1102 <        int n = count;
1103 <        if (n <= items.length)
1104 <            a = Arrays.copyOf(items, n);
1105 <        else
1106 <            retry = true;
1107 <        if (retry || lock.getSequence() != seq) {
1108 <            lock.lock();
1109 <            try {
1110 <                n = count;
1124 <                a = Arrays.copyOf(array, n);
1125 <            } finally {
1126 <                lock.unlock();
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(a, n, capacityIncrement);
1115 >        return new ReadMostlyVector<E>(a, n, capacityIncrement);
1116      }
1117  
1118      private void writeObject(java.io.ObjectOutputStream s)
1119 <            throws java.io.IOException {
1120 <        SequenceLock lock = this.lock;
1121 <        lock.lock();
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.unlock();
1125 >            lock.unlockRead(stamp);
1126          }
1127      }
1128  
1129 <    static final class Itr<E> implements ListIterator<E>, Enumeration<E>  {
1129 >    static final class Itr<E> implements ListIterator<E>, Enumeration<E> {
1130 >        final StampedLock lock;
1131          final ReadMostlyVector<E> list;
1145        final SequenceLock lock;
1132          Object[] items;
1147        Object next, prev;
1133          long seq;
1134          int cursor;
1135          int fence;
1136          int lastRet;
1152        boolean validNext, validPrev;
1137  
1138          Itr(ReadMostlyVector<E> list, int index) {
1139 <            this.list = list;
1140 <            this.lock = list.lock;
1141 <            this.cursor = index;
1142 <            this.lastRet = -1;
1143 <            refresh();
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 <        private void refresh() {
1156 <            validNext = validPrev = false;
1166 <            do {
1167 <                seq = lock.awaitAvailability();
1168 <                items = list.array;
1169 <            } while ((fence = list.count) > items.length ||
1170 <                     lock.getSequence() != seq);
1155 >        public boolean hasPrevious() {
1156 >            return cursor > 0;
1157          }
1158  
1159 <        public boolean hasNext() {
1160 <            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;
1159 >        public int nextIndex() {
1160 >            return cursor;
1161          }
1162  
1163 <        public boolean hasPrevious() {
1164 <            boolean valid;
1165 <            int i = cursor - 1;
1166 <            for (;;) {
1167 <                if (i >= fence || i < 0 || i >= items.length) {
1168 <                    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;
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 <            if (validNext || hasNext()) {
1173 <                validNext = false;
1174 <                lastRet = cursor++;
1175 <                return (E) next;
1176 <            }
1177 <            throw new NoSuchElementException();
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 <            if (validPrev || hasPrevious()) {
1186 <                validPrev = false;
1187 <                lastRet = cursor--;
1188 <                return (E) prev;
1189 <            }
1190 <            throw new NoSuchElementException();
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 <            lock.lock();
1201 >            if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1202 >                throw new ConcurrentModificationException();
1203              try {
1204 <                if (i < list.count)
1205 <                    list.remove(i);
1204 >                list.rawRemoveAt(i);
1205 >                fence = list.count;
1206 >                cursor = i;
1207 >                lastRet = -1;
1208              } finally {
1209 <                lock.unlock();
1209 >                seq = lock.tryConvertToOptimisticRead(seq);
1210              }
1238            cursor = i;
1239            lastRet = -1;
1240            refresh();
1211          }
1212  
1213          public void set(E e) {
1214              int i = lastRet;
1215 <            if (i < 0)
1215 >            Object[] es = items;
1216 >            if (es == null || i < 0 | i >= fence)
1217                  throw new IllegalStateException();
1218 <            lock.lock();
1218 >            if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1219 >                throw new ConcurrentModificationException();
1220              try {
1221 <                if (i < list.count)
1250 <                    list.set(i, e);
1221 >                es[i] = e;
1222              } finally {
1223 <                lock.unlock();
1223 >                seq = lock.tryConvertToOptimisticRead(seq);
1224              }
1254            refresh();
1225          }
1226  
1227          public void add(E e) {
1228              int i = cursor;
1229              if (i < 0)
1230                  throw new IllegalStateException();
1231 <            lock.lock();
1231 >            if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1232 >                throw new ConcurrentModificationException();
1233              try {
1234 <                if (i <= list.count)
1235 <                    list.add(i, e);
1234 >                list.rawAddAt(i, e);
1235 >                items = list.array;
1236 >                fence = list.count;
1237 >                cursor = i + 1;
1238 >                lastRet = -1;
1239              } finally {
1240 <                lock.unlock();
1240 >                seq = lock.tryConvertToOptimisticRead(seq);
1241              }
1268            cursor = i + 1;
1269            lastRet = -1;
1270            refresh();
1242          }
1243  
1244          public boolean hasMoreElements() { return hasNext(); }
1245          public E nextElement() { return next(); }
1275        public int nextIndex() { return cursor; }
1276        public int previousIndex() { return cursor - 1; }
1246      }
1247  
1248 <    static final class ReadMostlyVectorSublist<E> implements List<E>, RandomAccess, java.io.Serializable {
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, int offset, int size) {
1256 >        ReadMostlyVectorSublist(ReadMostlyVector<E> list,
1257 >                                int offset, int size) {
1258              this.list = list;
1259              this.offset = offset;
1260              this.size = size;
# Line 1293 | Line 1266 | public class ReadMostlyVector<E> impleme
1266          }
1267  
1268          public boolean add(E element) {
1269 <            SequenceLock lock = list.lock;
1270 <            lock.lock();
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.unlock();
1276 >                lock.unlockWrite(stamp);
1277              }
1278              return true;
1279          }
1280  
1281          public void add(int index, E element) {
1282 <            SequenceLock lock = list.lock;
1283 <            lock.lock();
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.unlock();
1290 >                lock.unlockWrite(stamp);
1291              }
1292          }
1293  
1294          public boolean addAll(Collection<? extends E> c) {
1295              Object[] elements = c.toArray();
1296 <            int added;
1297 <            SequenceLock lock = list.lock;
1325 <            lock.lock();
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 <                added = list.count - pc;
1302 >                int added = list.count - pc;
1303                  size = s + added;
1304 +                return added != 0;
1305              } finally {
1306 <                lock.unlock();
1306 >                lock.unlockWrite(stamp);
1307              }
1335            return added != 0;
1308          }
1309  
1310          public boolean addAll(int index, Collection<? extends E> c) {
1311              Object[] elements = c.toArray();
1312 <            int added;
1313 <            SequenceLock lock = list.lock;
1342 <            lock.lock();
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 <                added = list.count - pc;
1320 >                int added = list.count - pc;
1321                  size = s + added;
1322 +                return added != 0;
1323              } finally {
1324 <                lock.unlock();
1324 >                lock.unlockWrite(stamp);
1325              }
1354            return added != 0;
1326          }
1327  
1328          public void clear() {
1329 <            SequenceLock lock = list.lock;
1330 <            lock.lock();
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.unlock();
1335 >                lock.unlockWrite(stamp);
1336              }
1337          }
1338  
# Line 1370 | Line 1341 | public class ReadMostlyVector<E> impleme
1341          }
1342  
1343          public boolean containsAll(Collection<?> c) {
1344 <            return list.internalContainsAll(c, offset, offset + size);
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) {
# Line 1378 | Line 1355 | public class ReadMostlyVector<E> impleme
1355                  return true;
1356              if (!(o instanceof List))
1357                  return false;
1358 <            return list.internalEquals((List<?>)(o), offset, offset + size);
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) {
# Line 1388 | Line 1371 | public class ReadMostlyVector<E> impleme
1371          }
1372  
1373          public int hashCode() {
1374 <            return list.internalHashCode(offset, offset + size);
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 <            SequenceLock lock = list.lock;
1385 <            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();
1384 >            final StampedLock lock = list.lock;
1385 >            long stamp = lock.readLock();
1386              try {
1387 <                int idx = list.rawIndexOf(o, offset, offset + size);
1387 >                int idx = findFirstIndex(list.array, o, offset, offset + size);
1388                  return idx < 0 ? -1 : idx - offset;
1389              } finally {
1390 <                lock.unlock();
1390 >                lock.unlockRead(stamp);
1391              }
1392          }
1393  
1394          public boolean isEmpty() {
1395 <            return size == 0;
1395 >            return size() == 0;
1396          }
1397  
1398          public Iterator<E> iterator() {
1399 <            return new SubItr(this, offset);
1399 >            return new SubItr<E>(this, offset);
1400          }
1401  
1402          public int lastIndexOf(Object o) {
1403 <            SequenceLock lock = list.lock;
1404 <            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();
1403 >            final StampedLock lock = list.lock;
1404 >            long stamp = lock.readLock();
1405              try {
1406 <                int idx = list.rawLastIndexOf(o, offset + size - 1, offset);
1406 >                int idx = findLastIndex(list.array, o, offset + size - 1, offset);
1407                  return idx < 0 ? -1 : idx - offset;
1408              } finally {
1409 <                lock.unlock();
1409 >                lock.unlockRead(stamp);
1410              }
1411          }
1412  
1413          public ListIterator<E> listIterator() {
1414 <            return new SubItr(this, offset);
1414 >            return new SubItr<E>(this, offset);
1415          }
1416  
1417          public ListIterator<E> listIterator(int index) {
1418 <            return new SubItr(this, index + offset);
1418 >            return new SubItr<E>(this, index + offset);
1419          }
1420  
1421          public E remove(int index) {
1422 <            Object result;
1423 <            SequenceLock lock = list.lock;
1453 <            lock.lock();
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 (index < 0 || index >= size || i >= items.length)
1427 >                if (items == null || index < 0 || index >= size || i >= items.length)
1428                      throw new ArrayIndexOutOfBoundsException(index);
1429 <                result = items[i];
1429 >                @SuppressWarnings("unchecked") E result = (E)items[i];
1430                  list.rawRemoveAt(i);
1431                  size--;
1432 +                return result;
1433              } finally {
1434 <                lock.unlock();
1434 >                lock.unlockWrite(stamp);
1435              }
1465            return (E)result;
1436          }
1437  
1438          public boolean remove(Object o) {
1439 <            boolean removed = false;
1440 <            SequenceLock lock = list.lock;
1441 <            lock.lock();
1442 <            try {
1443 <                if (list.rawRemoveAt(list.rawIndexOf(o, offset,
1474 <                                                     offset + size))) {
1475 <                    removed = true;
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.unlock();
1450 >                lock.unlockWrite(stamp);
1451              }
1481            return removed;
1452          }
1453  
1454          public boolean removeAll(Collection<?> c) {
1455 <            return list.internalRemoveAll(c, offset, offset + size);
1455 >            return list.lockedRemoveAll(c, offset, offset + size);
1456          }
1457  
1458          public boolean retainAll(Collection<?> c) {
1459 <            return list.internalRetainAll(c, offset, offset + size);
1459 >            return list.lockedRetainAll(c, offset, offset + size);
1460          }
1461  
1462          public E set(int index, E element) {
# Line 1502 | Line 1472 | public class ReadMostlyVector<E> impleme
1472          public List<E> subList(int fromIndex, int toIndex) {
1473              int c = size;
1474              int ssize = toIndex - fromIndex;
1475 <            if (fromIndex < 0 || toIndex > c || ssize < 0)
1476 <                throw new IndexOutOfBoundsException();
1477 <            return new ReadMostlyVectorSublist(list, offset+fromIndex, ssize);
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 <            return list.internalToArray(offset, offset + size);
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 <            return list.internalToArray(a, offset, offset + size);
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 <            return list.internalToString(offset, offset + size);
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      }
# Line 1524 | Line 1514 | public class ReadMostlyVector<E> impleme
1514      static final class SubItr<E> implements ListIterator<E> {
1515          final ReadMostlyVectorSublist<E> sublist;
1516          final ReadMostlyVector<E> list;
1517 <        final SequenceLock lock;
1517 >        final StampedLock lock;
1518          Object[] items;
1529        Object next, prev;
1519          long seq;
1520          int cursor;
1521 +        int origin;
1522          int fence;
1523          int lastRet;
1534        boolean validNext, validPrev;
1524  
1525          SubItr(ReadMostlyVectorSublist<E> sublist, int index) {
1526 <            this.sublist = sublist;
1527 <            this.list = sublist.list;
1528 <            this.lock = list.lock;
1529 <            this.cursor = index;
1530 <            this.lastRet = -1;
1531 <            refresh();
1532 <            if (index < 0 || index > fence)
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 <        private void refresh() {
1544 <            validNext = validPrev = false;
1545 <            do {
1546 <                int n;
1547 <                seq = lock.awaitAvailability();
1548 <                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);
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 <            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;
1552 >            return cursor < fence;
1553          }
1554  
1555          public boolean hasPrevious() {
1556 <            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;
1556 >            return cursor > origin;
1557          }
1558  
1559          public E next() {
1560 <            if (validNext || hasNext()) {
1561 <                validNext = false;
1562 <                lastRet = cursor++;
1563 <                return (E) next;
1564 <            }
1565 <            throw new NoSuchElementException();
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 <            if (validPrev || hasPrevious()) {
1574 <                validPrev = false;
1575 <                lastRet = cursor--;
1576 <                return (E) prev;
1577 <            }
1578 <            throw new NoSuchElementException();
1579 <        }
1580 <
1581 <        public int nextIndex() {
1582 <            return cursor - sublist.offset;
1616 <        }
1617 <
1618 <        public int previousIndex() {
1619 <            return cursor - 1 - sublist.offset;
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 <            cursor = i;
1590 <            lastRet = -1;
1628 <            lock.lock();
1589 >            if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1590 >                throw new ConcurrentModificationException();
1591              try {
1592 <                if (i < list.count) {
1593 <                    list.remove(i);
1594 <                    --sublist.size;
1595 <                }
1592 >                list.rawRemoveAt(i);
1593 >                fence = origin + sublist.size;
1594 >                cursor = i;
1595 >                lastRet = -1;
1596              } finally {
1597 <                lock.unlock();
1597 >                seq = lock.tryConvertToOptimisticRead(seq);
1598              }
1637            refresh();
1599          }
1600  
1601          public void set(E e) {
1602              int i = lastRet;
1603 <            if (i < 0)
1603 >            if (i < origin || i >= fence)
1604                  throw new IllegalStateException();
1605 <            lock.lock();
1605 >            if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1606 >                throw new ConcurrentModificationException();
1607              try {
1608 <                if (i < list.count)
1647 <                    list.set(i, e);
1608 >                list.set(i, e);
1609              } finally {
1610 <                lock.unlock();
1610 >                seq = lock.tryConvertToOptimisticRead(seq);
1611              }
1651            refresh();
1612          }
1613  
1614          public void add(E e) {
1615              int i = cursor;
1616 <            if (i < 0)
1616 >            if (i < origin || i >= fence)
1617                  throw new IllegalStateException();
1618 <            cursor = i + 1;
1619 <            lastRet = -1;
1660 <            lock.lock();
1618 >            if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1619 >                throw new ConcurrentModificationException();
1620              try {
1621 <                if (i <= list.count) {
1622 <                    list.add(i, e);
1623 <                    ++sublist.size;
1624 <                }
1621 >                list.rawAddAt(i, e);
1622 >                items = list.array;
1623 >                fence = origin + sublist.size;
1624 >                cursor = i + 1;
1625 >                lastRet = -1;
1626              } finally {
1627 <                lock.unlock();
1627 >                seq = lock.tryConvertToOptimisticRead(seq);
1628              }
1669            refresh();
1629          }
1671
1630      }
1631   }
1674

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines