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.13 by jsr166, Fri Aug 5 17:08:04 2011 UTC vs.
Revision 1.30 by jsr166, Fri Oct 12 16:27:47 2012 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 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
66 <    volatile Object[] array;
67 <    final SequenceLock lock;
68 <    volatile int count;
65 >    // fields are non-private to simplify nested class access
66 >    Object[] array;
67 >    final StampedLock lock;
68 >    int count;
69      final int capacityIncrement;
70  
71      /**
# 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      /**
# Line 95 | Line 101 | public class ReadMostlyVector<E> impleme
101      }
102  
103      /**
104 <     * Creates an empty vector with an underlying array of size {@code 10}.
104 >     * Creates an empty vector.
105       */
106      public ReadMostlyVector() {
107 <        this(10, 0);
107 >        this.capacityIncrement = 0;
108 >        this.lock = new StampedLock();
109      }
110  
111      /**
# Line 117 | Line 124 | public class ReadMostlyVector<E> impleme
124          this.array = elements;
125          this.count = elements.length;
126          this.capacityIncrement = 0;
127 <        this.lock = new SequenceLock();
127 >        this.lock = new StampedLock();
128      }
129  
130      // internal constructor for clone
# Line 125 | Line 132 | public class ReadMostlyVector<E> impleme
132          this.array = array;
133          this.count = count;
134          this.capacityIncrement = capacityIncrement;
135 <        this.lock = new SequenceLock();
135 >        this.lock = new StampedLock();
136      }
137  
138 +    static final int INITIAL_CAP = 16;
139 +
140      // For explanation, see CopyOnWriteArrayList
141      final Object[] grow(int minCapacity) {
142 <        int oldCapacity = array.length;
143 <        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
142 >        Object[] items;
143 >        int newCapacity;
144 >        if ((items = array) == null)
145 >            newCapacity = INITIAL_CAP;
146 >        else {
147 >            int oldCapacity = array.length;
148 >            newCapacity = oldCapacity + ((capacityIncrement > 0) ?
149                                           capacityIncrement : oldCapacity);
150 +        }
151          if (newCapacity - minCapacity < 0)
152              newCapacity = minCapacity;
153 <        if (newCapacity - MAX_ARRAY_SIZE > 0)
154 <            newCapacity = hugeCapacity(minCapacity);
155 <        return array = Arrays.copyOf(array, newCapacity);
156 <    }
157 <
158 <    static int hugeCapacity(int minCapacity) {
159 <        if (minCapacity < 0) // overflow
160 <            throw new OutOfMemoryError();
161 <        return (minCapacity > MAX_ARRAY_SIZE) ?
162 <            Integer.MAX_VALUE :
163 <            MAX_ARRAY_SIZE;
153 >        if (newCapacity - MAX_ARRAY_SIZE > 0) {
154 >            if (minCapacity < 0) // overflow
155 >                throw new OutOfMemoryError();
156 >            else if (minCapacity > MAX_ARRAY_SIZE)
157 >                newCapacity = Integer.MAX_VALUE;
158 >            else
159 >                newCapacity = MAX_ARRAY_SIZE;
160 >        }
161 >        return array = ((items == null) ?
162 >                        new Object[newCapacity] :
163 >                        Arrays.copyOf(items, newCapacity));
164      }
165  
166      /*
# Line 154 | Line 169 | public class ReadMostlyVector<E> impleme
169       * as well as sublist and iterator classes.
170       */
171  
172 <    // Version of indexOf that returns -1 if either not present or invalid
173 <    final int validatedIndexOf(Object x, Object[] items, int index, int fence,
174 <                               long seq) {
175 <        for (int i = index; i < fence; ++i) {
176 <            Object e = items[i];
177 <            if (lock.getSequence() != seq)
178 <                break;
179 <            if ((x == null) ? e == null : x.equals(e))
180 <                return i;
181 <        }
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;
172 >    static int findFirstIndex(Object[] items, Object x, int index, int fence) {
173 >        int len;
174 >        if (items != null && (len = items.length) > 0) {
175 >            int start = (index < 0) ? 0 : index;
176 >            int bound = (fence < len) ? fence : len;
177 >            for (int i = start; i < bound; ++i) {
178 >                Object e = items[i];
179 >                if ((x == null) ? e == null : x.equals(e))
180 >                    return i;
181 >            }
182          }
183          return -1;
184      }
185  
186 <    final int rawLastIndexOf(Object x, int index, int origin) {
187 <        Object[] items = array;
188 <        for (int i = index; i >= origin; --i) {
189 <            Object e = items[i];
190 <            if ((x == null) ? e == null : x.equals(e))
191 <                return i;
186 >    static int findLastIndex(Object[] items, Object x, int index, int origin) {
187 >        int len;
188 >        if (items != null && (len = items.length) > 0) {
189 >            int last = (index < len) ? index : len - 1;
190 >            int start = (origin < 0) ? 0 : origin;
191 >            for (int i = last; i >= start; --i) {
192 >                Object e = items[i];
193 >                if ((x == null) ? e == null : x.equals(e))
194 >                    return i;
195 >            }
196          }
197          return -1;
198      }
199  
200 <    final void rawAdd(Object e) {
200 >    final void rawAdd(E e) {
201          int n = count;
202          Object[] items = array;
203 <        if (n >= items.length)
203 >        if (items == null || n >= items.length)
204              items = grow(n + 1);
205          items[n] = e;
206          count = n + 1;
207      }
208  
209 <    final void rawAddAt(int index, Object e) {
209 >    final void rawAddAt(int index, E e) {
210          int n = count;
211          Object[] items = array;
212          if (index > n)
213              throw new ArrayIndexOutOfBoundsException(index);
214 <        if (n >= items.length)
214 >        if (items == null || n >= items.length)
215              items = grow(n + 1);
216          if (index < n)
217              System.arraycopy(items, index, items, index + 1, n - index);
# Line 230 | Line 228 | public class ReadMostlyVector<E> impleme
228          if (len == 0)
229              return false;
230          int newCount = n + len;
231 <        if (newCount >= items.length)
231 >        if (items == null || newCount >= items.length)
232              items = grow(newCount);
233          int mv = n - index;
234          if (mv > 0)
# Line 243 | Line 241 | public class ReadMostlyVector<E> impleme
241      final boolean rawRemoveAt(int index) {
242          int n = count - 1;
243          Object[] items = array;
244 <        if (index < 0 || index > n)
244 >        if (items == null || index < 0 || index > n)
245              return false;
246          int mv = n - index;
247          if (mv > 0)
# Line 260 | Line 258 | public class ReadMostlyVector<E> impleme
258       * is left negative if the bound should be determined via count
259       * field under lock.
260       */
261 <    final boolean internalRemoveAll(Collection<?> c, int origin, int bound) {
264 <        SequenceLock lock = this.lock;
261 >    final boolean lockedRemoveAll(Collection<?> c, int origin, int bound) {
262          boolean removed = false;
263 <        lock.lock();
263 >        final StampedLock lock = this.lock;
264 >        long stamp = lock.writeLock();
265          try {
266              int n = count;
267              int fence = bound < 0 || bound > n ? n : bound;
268              if (origin >= 0 && origin < fence) {
269                  for (Object x : c) {
270 <                    while (rawRemoveAt(rawIndexOf(x, origin, fence)))
270 >                    while (rawRemoveAt(findFirstIndex(array, x, origin, fence)))
271                          removed = true;
272                  }
273              }
274          } finally {
275 <            lock.unlock();
275 >            lock.unlockWrite(stamp);
276          }
277          return removed;
278      }
279  
280 <    final boolean internalRetainAll(Collection<?> c, int origin, int bound) {
281 <        SequenceLock lock = this.lock;
280 >    final boolean lockedRetainAll(Collection<?> c, int origin, int bound) {
281 >        final StampedLock lock = this.lock;
282          boolean removed = false;
283          if (c != this) {
284 <            lock.lock();
284 >            long stamp = lock.writeLock();
285              try {
286 <                Object[] items = array;
287 <                int i = origin;
288 <                int n = count;
289 <                int fence = bound < 0 || bound > n ? n : bound;
290 <                while (i >= 0 && 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);
286 >                Object[] items;
287 >                int i, n;
288 >                if ((items = array) != null && (n = count) > 0 &&
289 >                    n < items.length && (i = origin) >= 0) {
290 >                    int fence = bound < 0 || bound > n ? n : bound;
291 >                    while (i < fence) {
292 >                        if (c.contains(items[i]))
293 >                            ++i;
294 >                        else {
295 >                            --fence;
296 >                            int mv = --n - i;
297 >                            if (mv > 0)
298 >                                System.arraycopy(items, i + 1, items, i, mv);
299 >                        }
300 >                    }
301 >                    if (count != n) {
302 >                        count = n;
303 >                        removed = true;
304                      }
301                }
302                if (count != n) {
303                    count = n;
304                    removed = true;
305                  }
306              } finally {
307 <                lock.unlock();
307 >                lock.unlockWrite(stamp);
308              }
309          }
310          return removed;
311      }
312  
313      final void internalClear(int origin, int bound) {
314 <        int n = count;
315 <        int fence = bound < 0 || bound > n ? n : bound;
316 <        if (origin >= 0 && origin < fence) {
317 <            Object[] items = array;
314 >        Object[] items;
315 >        int n, len;
316 >        if ((items = array) != null && (len = items.length) > 0) {
317 >            if (origin < 0)
318 >                origin = 0;
319 >            if ((n = count) > len)
320 >                n = len;
321 >            int fence = bound < 0 || bound > n ? n : bound;
322              int removed = fence - origin;
323              int newCount = n - removed;
324              int mv = n - (origin + removed);
# Line 327 | Line 331 | public class ReadMostlyVector<E> impleme
331      }
332  
333      final boolean internalContainsAll(Collection<?> c, int origin, int bound) {
334 <        SequenceLock lock = this.lock;
335 <        boolean contained;
336 <        boolean locked = false;
337 <        try {
338 <            for (;;) {
339 <                long seq = lock.awaitAvailability();
340 <                int n = count;
341 <                Object[] items = array;
342 <                int len = items.length;
343 <                if (n > len)
344 <                    continue;
341 <                int fence = bound < 0 || bound > n ? n : bound;
342 <                if (origin < 0)
343 <                    contained = false;
344 <                else {
345 <                    contained = true;
346 <                    for (Object e : c) {
347 <                        int idx = (locked ?
348 <                                   rawIndexOf(e, origin, fence) :
349 <                                   validatedIndexOf(e, items, origin,
350 <                                                    fence, seq));
351 <                        if (idx < 0) {
352 <                            contained = false;
353 <                            break;
354 <                        }
355 <                    }
356 <                }
357 <                if (lock.getSequence() == seq)
358 <                    break;
359 <                lock.lock();
360 <                locked = true;
334 >        Object[] items;
335 >        int n, len;
336 >        if ((items = array) != null && (len = items.length) > 0) {
337 >            if (origin < 0)
338 >                origin = 0;
339 >            if ((n = count) > len)
340 >                n = len;
341 >            int fence = bound < 0 || bound > n ? n : bound;
342 >            for (Object e : c) {
343 >                if (findFirstIndex(items, e, origin, fence) < 0)
344 >                    return false;
345              }
362        } finally {
363            if (locked)
364                lock.unlock();
346          }
347 <        return contained;
347 >        else if (!c.isEmpty())
348 >            return false;
349 >        return true;
350      }
351  
352      final boolean internalEquals(List<?> list, int origin, int bound) {
353 <        SequenceLock lock = this.lock;
354 <        boolean locked = false;
355 <        boolean equal;
356 <        try {
357 <            for (;;) {
358 <                long seq = lock.awaitAvailability();
359 <                Object[] items = array;
360 <                int n = count;
361 <                if (n > items.length || origin < 0)
362 <                    equal = false;
363 <                else {
364 <                    equal = true;
365 <                    int fence = bound < 0 || bound > n ? n : bound;
366 <                    Iterator<?> it = list.iterator();
367 <                    for (int i = origin; i < fence; ++i) {
368 <                        Object x = items[i];
386 <                        Object y;
387 <                        if ((!locked && lock.getSequence() != seq) ||
388 <                            !it.hasNext() ||
389 <                            (y = it.next()) == null ?
390 <                            x != null : !y.equals(x)) {
391 <                            equal = false;
392 <                            break;
393 <                        }
394 <                    }
395 <                    if (equal && it.hasNext())
396 <                        equal = false;
397 <                }
398 <                if (lock.getSequence() == seq)
399 <                    break;
400 <                lock.lock();
401 <                locked = true;
353 >        Object[] items;
354 >        int n, len;
355 >        if ((items = array) != null && (len = items.length) > 0) {
356 >            if (origin < 0)
357 >                origin = 0;
358 >            if ((n = count) > len)
359 >                n = len;
360 >            int fence = bound < 0 || bound > n ? n : bound;
361 >            Iterator<?> it = list.iterator();
362 >            for (int i = origin; i < fence; ++i) {
363 >                if (!it.hasNext())
364 >                    return false;
365 >                Object y = it.next();
366 >                Object x = items[i];
367 >                if (x != y && (x == null || !x.equals(y)))
368 >                    return false;
369              }
370 <        } finally {
371 <            if (locked)
405 <                lock.unlock();
370 >            if (it.hasNext())
371 >                return false;
372          }
373 <        return equal;
373 >        else if (!list.isEmpty())
374 >            return false;
375 >        return true;
376      }
377  
378      final int internalHashCode(int origin, int bound) {
379 <        SequenceLock lock = this.lock;
380 <        int hash;
381 <        boolean locked = false;
382 <        try {
383 <            for (;;) {
384 <                hash = 1;
385 <                long seq = lock.awaitAvailability();
386 <                Object[] items = array;
387 <                int n = count;
388 <                int len = items.length;
389 <                if (n > len)
390 <                    continue;
423 <                int fence = bound < 0 || bound > n ? n : bound;
424 <                if (origin >= 0) {
425 <                    for (int i = origin; i < fence; ++i) {
426 <                        Object e = items[i];
427 <                        hash = 31*hash + (e == null ? 0 : e.hashCode());
428 <                    }
429 <                }
430 <                if (lock.getSequence() == seq)
431 <                    break;
432 <                lock.lock();
433 <                locked = true;
379 >        int hash = 1;
380 >        Object[] items;
381 >        int n, len;
382 >        if ((items = array) != null && (len = items.length) > 0) {
383 >            if (origin < 0)
384 >                origin = 0;
385 >            if ((n = count) > len)
386 >                n = len;
387 >            int fence = bound < 0 || bound > n ? n : bound;
388 >            for (int i = origin; i < fence; ++i) {
389 >                Object e = items[i];
390 >                hash = 31*hash + (e == null ? 0 : e.hashCode());
391              }
435        } finally {
436            if (locked)
437                lock.unlock();
392          }
393          return hash;
394      }
395  
396      final String internalToString(int origin, int bound) {
397 <        SequenceLock lock = this.lock;
398 <        String ret;
399 <        boolean locked = false;
400 <        try {
401 <            outer:for (;;) {
402 <                long seq = lock.awaitAvailability();
403 <                Object[] items = array;
404 <                int n = count;
405 <                int len = items.length;
406 <                if (n > len)
407 <                    continue;
408 <                int fence = bound < 0 || bound > n ? n : bound;
409 <                if (origin < 0 || origin == fence)
410 <                    ret = "[]";
411 <                else {
412 <                    StringBuilder sb = new StringBuilder();
413 <                    sb.append('[');
460 <                    for (int i = origin;;) {
461 <                        Object e = items[i];
462 <                        if (e == this)
463 <                            sb.append("(this Collection)");
464 <                        else if (!locked && lock.getSequence() != seq)
465 <                            continue outer;
466 <                        else
467 <                            sb.append(e.toString());
468 <                        if (++i < fence)
469 <                            sb.append(',').append(' ');
470 <                        else {
471 <                            ret = sb.append(']').toString();
472 <                            break;
473 <                        }
474 <                    }
397 >        Object[] items;
398 >        int n, len;
399 >        if ((items = array) != null && (len = items.length) > 0) {
400 >            if ((n = count) > len)
401 >                n = len;
402 >            int fence = bound < 0 || bound > n ? n : bound;
403 >            int i = (origin < 0) ? 0 : origin;
404 >            if (i != fence) {
405 >                StringBuilder sb = new StringBuilder();
406 >                sb.append('[');
407 >                for (;;) {
408 >                    Object e = items[i];
409 >                    sb.append((e == this) ? "(this Collection)" : e.toString());
410 >                    if (++i < fence)
411 >                        sb.append(',').append(' ');
412 >                    else
413 >                        return sb.append(']').toString();
414                  }
476                if (lock.getSequence() == seq)
477                    break;
478                lock.lock();
479                locked = true;
415              }
481        } finally {
482            if (locked)
483                lock.unlock();
416          }
417 <        return ret;
417 >        return "[]";
418      }
419  
420      final Object[] internalToArray(int origin, int bound) {
421 <        Object[] result;
422 <        SequenceLock lock = this.lock;
423 <        boolean locked = false;
424 <        try {
425 <            for (;;) {
426 <                result = null;
427 <                long seq = lock.awaitAvailability();
428 <                Object[] items = array;
429 <                int n = count;
430 <                int len = items.length;
431 <                if (n > len)
500 <                    continue;
501 <                int fence = bound < 0 || bound > n ? n : bound;
502 <                if (origin >= 0)
503 <                    result = Arrays.copyOfRange(items, origin, fence,
504 <                                                Object[].class);
505 <                if (lock.getSequence() == seq)
506 <                    break;
507 <                lock.lock();
508 <                locked = true;
509 <            }
510 <        } finally {
511 <            if (locked)
512 <                lock.unlock();
421 >        Object[] items;
422 >        int n, len;
423 >        if ((items = array) != null && (len = items.length) > 0) {
424 >            if (origin < 0)
425 >                origin = 0;
426 >            if ((n = count) > len)
427 >                n = len;
428 >            int fence = bound < 0 || bound > n ? n : bound;
429 >            int i = (origin < 0) ? 0 : origin;
430 >            if (i != fence)
431 >                return Arrays.copyOfRange(items, i, fence, Object[].class);
432          }
433 <        return result;
433 >        return new Object[0];
434      }
435  
436 +    @SuppressWarnings("unchecked")
437      final <T> T[] internalToArray(T[] a, int origin, int bound) {
438          int alen = a.length;
439 <        T[] result;
440 <        SequenceLock lock = this.lock;
441 <        boolean locked = false;
442 <        try {
443 <            for (;;) {
444 <                long seq = lock.awaitAvailability();
445 <                Object[] items = array;
446 <                int n = count;
447 <                int len = items.length;
448 <                if (n > len)
449 <                    continue;
450 <                int fence = bound < 0 || bound > n ? n : bound;
451 <                int rlen = fence - origin;
532 <                if (rlen < 0)
533 <                    rlen = 0;
534 <                if (origin < 0 || alen >= rlen) {
535 <                    if (rlen > 0)
536 <                        System.arraycopy(items, 0, a, origin, rlen);
439 >        Object[] items;
440 >        int n, len;
441 >        if ((items = array) != null && (len = items.length) > 0) {
442 >            if (origin < 0)
443 >                origin = 0;
444 >            if ((n = count) > len)
445 >                n = len;
446 >            int fence = bound < 0 || bound > n ? n : bound;
447 >            int i = (origin < 0) ? 0 : origin;
448 >            int rlen = fence - origin;
449 >            if (rlen > 0) {
450 >                if (alen >= rlen) {
451 >                    System.arraycopy(items, 0, a, origin, rlen);
452                      if (alen > rlen)
453                          a[rlen] = null;
454 <                    result = a;
454 >                    return a;
455                  }
456 <                else
542 <                    result = (T[]) Arrays.copyOfRange(items, origin,
543 <                                                      fence, a.getClass());
544 <                if (lock.getSequence() == seq)
545 <                    break;
546 <                lock.lock();
547 <                locked = true;
456 >                return (T[]) Arrays.copyOfRange(items, i, fence, a.getClass());
457              }
549        } finally {
550            if (locked)
551                lock.unlock();
458          }
459 <        return result;
459 >        if (alen > 0)
460 >            a[0] = null;
461 >        return a;
462      }
463  
464      // public List methods
465  
466      public boolean add(E e) {
467 <        SequenceLock lock = this.lock;
468 <        lock.lock();
467 >        final StampedLock lock = this.lock;
468 >        long stamp = lock.writeLock();
469          try {
470              rawAdd(e);
471          } finally {
472 <            lock.unlock();
472 >            lock.unlockWrite(stamp);
473          }
474          return true;
475      }
476  
477      public void add(int index, E element) {
478 <        SequenceLock lock = this.lock;
479 <        lock.lock();
478 >        final StampedLock lock = this.lock;
479 >        long stamp = lock.writeLock();
480          try {
481              rawAddAt(index, element);
482          } finally {
483 <            lock.unlock();
483 >            lock.unlockWrite(stamp);
484          }
485      }
486  
# Line 581 | Line 489 | public class ReadMostlyVector<E> impleme
489          int len = elements.length;
490          if (len == 0)
491              return false;
492 <        SequenceLock lock = this.lock;
493 <        lock.lock();
492 >        final StampedLock lock = this.lock;
493 >        long stamp = lock.writeLock();
494          try {
495              Object[] items = array;
496              int n = count;
497              int newCount = n + len;
498 <            if (newCount >= items.length)
498 >            if (items == null || newCount >= items.length)
499                  items = grow(newCount);
500              System.arraycopy(elements, 0, items, n, len);
501              count = newCount;
502          } finally {
503 <            lock.unlock();
503 >            lock.unlockWrite(stamp);
504          }
505          return true;
506      }
507  
508      public boolean addAll(int index, Collection<? extends E> c) {
601        SequenceLock lock = this.lock;
602        boolean ret;
509          Object[] elements = c.toArray();
510 <        lock.lock();
510 >        boolean ret;
511 >        final StampedLock lock = this.lock;
512 >        long stamp = lock.writeLock();
513          try {
514              ret = rawAddAllAt(index, elements);
515          } finally {
516 <            lock.unlock();
516 >            lock.unlockWrite(stamp);
517          }
518          return ret;
519      }
520  
521      public void clear() {
522 <        SequenceLock lock = this.lock;
523 <        lock.lock();
522 >        final StampedLock lock = this.lock;
523 >        long stamp = lock.writeLock();
524          try {
525              int n = count;
526              Object[] items = array;
527 <            for (int i = 0; i < n; i++)
528 <                items[i] = null;
527 >            if (items != null) {
528 >                for (int i = 0; i < n; i++)
529 >                    items[i] = null;
530 >            }
531              count = 0;
532          } finally {
533 <            lock.unlock();
533 >            lock.unlockWrite(stamp);
534          }
535      }
536  
# Line 629 | Line 539 | public class ReadMostlyVector<E> impleme
539      }
540  
541      public boolean containsAll(Collection<?> c) {
542 <        return internalContainsAll(c, 0, -1);
542 >        boolean ret;
543 >        final StampedLock lock = this.lock;
544 >        long stamp = lock.readLock();
545 >        try {
546 >            ret = internalContainsAll(c, 0, -1);
547 >        } finally {
548 >            lock.unlockRead(stamp);
549 >        }
550 >        return ret;
551      }
552  
553      public boolean equals(Object o) {
# Line 637 | Line 555 | public class ReadMostlyVector<E> impleme
555              return true;
556          if (!(o instanceof List))
557              return false;
558 <        return internalEquals((List<?>)o, 0, -1);
558 >        final StampedLock lock = this.lock;
559 >        long stamp = lock.readLock();
560 >        try {
561 >            return internalEquals((List<?>)o, 0, -1);
562 >        } finally {
563 >            lock.unlockRead(stamp);
564 >        }
565      }
566  
567      public E get(int index) {
568 <        SequenceLock lock = this.lock;
569 <        for (;;) {
570 <            long seq = lock.awaitAvailability();
571 <            int n = count;
572 <            Object[] items = array;
573 <            if (n > items.length)
574 <                continue;
575 <            Object e; boolean ex;
576 <            if (index < 0 || index >= n) {
577 <                e = null;
578 <                ex = true;
579 <            }
580 <            else {
581 <                e = items[index];
582 <                ex = false;
583 <            }
584 <            if (lock.getSequence() == seq) {
585 <                if (ex)
586 <                    throw new ArrayIndexOutOfBoundsException(index);
587 <                else
588 <                    return (E)e;
589 <            }
568 >        final StampedLock lock = this.lock;
569 >        long stamp = lock.tryOptimisticRead();
570 >        Object[] items;
571 >        if (index >= 0 && (items = array) != null &&
572 >            index < count && index < items.length) {
573 >            @SuppressWarnings("unchecked") E e = (E)items[index];
574 >            if (lock.validate(stamp))
575 >                return e;
576 >        }
577 >        return lockedGet(index);
578 >    }
579 >
580 >    @SuppressWarnings("unchecked") private E lockedGet(int index) {
581 >        boolean oobe = false;
582 >        E e = null;
583 >        final StampedLock lock = this.lock;
584 >        long stamp = lock.readLock();
585 >        try {
586 >            Object[] items;
587 >            if ((items = array) != null && index < items.length &&
588 >                index < count && index >= 0)
589 >                e = (E)items[index];
590 >            else
591 >                oobe = true;
592 >        } finally {
593 >            lock.unlockRead(stamp);
594          }
595 +        if (oobe)
596 +            throw new ArrayIndexOutOfBoundsException(index);
597 +        return (E)e;
598      }
599  
600      public int hashCode() {
601 <        return internalHashCode(0, -1);
601 >        int h;
602 >        final StampedLock lock = this.lock;
603 >        long s = lock.readLock();
604 >        try {
605 >            h = internalHashCode(0, -1);
606 >        } finally {
607 >            lock.unlockRead(s);
608 >        }
609 >        return h;
610      }
611  
612      public int indexOf(Object o) {
613 <        SequenceLock lock = this.lock;
614 <        for (;;) {
615 <            long seq = lock.awaitAvailability();
616 <            Object[] items = array;
617 <            int n = count;
618 <            if (n <= items.length) {
619 <                for (int i = 0; i < n; ++i) {
681 <                    Object e = items[i];
682 <                    if (lock.getSequence() != seq) {
683 <                        lock.lock();
684 <                        try {
685 <                            return rawIndexOf(o, 0, count);
686 <                        } finally {
687 <                            lock.unlock();
688 <                        }
689 <                    }
690 <                    else if ((o == null) ? e == null : o.equals(e))
691 <                        return i;
692 <                }
693 <                return -1;
694 <            }
613 >        int idx;
614 >        final StampedLock lock = this.lock;
615 >        long stamp = lock.readLock();
616 >        try {
617 >            idx = findFirstIndex(array, o, 0, count);
618 >        } finally {
619 >            lock.unlockRead(stamp);
620          }
621 +        return idx;
622      }
623  
624      public boolean isEmpty() {
625 <        return count == 0;
625 >        final StampedLock lock = this.lock;
626 >        long stamp = lock.tryOptimisticRead();
627 >        return count == 0; // no need for validation
628      }
629  
630      public Iterator<E> iterator() {
# Line 704 | Line 632 | public class ReadMostlyVector<E> impleme
632      }
633  
634      public int lastIndexOf(Object o) {
635 <        SequenceLock lock = this.lock;
636 <        for (;;) {
637 <            long seq = lock.awaitAvailability();
638 <            Object[] items = array;
639 <            int n = count;
640 <            if (n <= items.length) {
641 <                for (int i = n - 1; i >= 0; --i) {
714 <                    Object e = items[i];
715 <                    if (lock.getSequence() != seq) {
716 <                        lock.lock();
717 <                        try {
718 <                            return rawLastIndexOf(o, 0, count);
719 <                        } finally {
720 <                            lock.unlock();
721 <                        }
722 <                    }
723 <                    else if ((o == null) ? e == null : o.equals(e))
724 <                        return i;
725 <                }
726 <                return -1;
727 <            }
635 >        int idx;
636 >        final StampedLock lock = this.lock;
637 >        long stamp = lock.readLock();
638 >        try {
639 >            idx = findLastIndex(array, o, count - 1, 0);
640 >        } finally {
641 >            lock.unlockRead(stamp);
642          }
643 +        return idx;
644      }
645  
646      public ListIterator<E> listIterator() {
# Line 736 | Line 651 | public class ReadMostlyVector<E> impleme
651          return new Itr<E>(this, index);
652      }
653  
654 <    public E remove(int index) {
655 <        SequenceLock lock = this.lock;
656 <        Object oldValue;
657 <        lock.lock();
654 >    @SuppressWarnings("unchecked") public E remove(int index) {
655 >        E oldValue = null;
656 >        boolean oobe = false;
657 >        final StampedLock lock = this.lock;
658 >        long stamp = lock.writeLock();
659          try {
660              if (index < 0 || index >= count)
661 <                throw new ArrayIndexOutOfBoundsException(index);
662 <            oldValue = array[index];
663 <            rawRemoveAt(index);
661 >                oobe = true;
662 >            else {
663 >                oldValue = (E) array[index];
664 >                rawRemoveAt(index);
665 >            }
666          } finally {
667 <            lock.unlock();
667 >            lock.unlockWrite(stamp);
668          }
669 <        return (E)oldValue;
669 >        if (oobe)
670 >            throw new ArrayIndexOutOfBoundsException(index);
671 >        return oldValue;
672      }
673  
674      public boolean remove(Object o) {
675 <        SequenceLock lock = this.lock;
676 <        boolean removed;
757 <        lock.lock();
675 >        final StampedLock lock = this.lock;
676 >        long stamp = lock.writeLock();
677          try {
678 <            removed = rawRemoveAt(rawIndexOf(o, 0, count));
678 >            return rawRemoveAt(findFirstIndex(array, o, 0, count));
679          } finally {
680 <            lock.unlock();
680 >            lock.unlockWrite(stamp);
681          }
763        return removed;
682      }
683  
684      public boolean removeAll(Collection<?> c) {
685 <        return internalRemoveAll(c, 0, -1);
685 >        return lockedRemoveAll(c, 0, -1);
686      }
687  
688      public boolean retainAll(Collection<?> c) {
689 <        return internalRetainAll(c, 0, -1);
689 >        return lockedRetainAll(c, 0, -1);
690      }
691  
692 <    public E set(int index, E element) {
693 <        Object oldValue;
694 <        SequenceLock lock = this.lock;
695 <        lock.lock();
692 >    @SuppressWarnings("unchecked") public E set(int index, E element) {
693 >        E oldValue = null;
694 >        boolean oobe = false;
695 >        final StampedLock lock = this.lock;
696 >        long stamp = lock.writeLock();
697          try {
698              Object[] items = array;
699 <            if (index < 0 || index >= count)
700 <                throw new ArrayIndexOutOfBoundsException(index);
701 <            oldValue = items[index];
702 <            items[index] = element;
699 >            if (items == null || index < 0 || index >= count)
700 >                oobe = true;
701 >            else {
702 >                oldValue = (E) items[index];
703 >                items[index] = element;
704 >            }
705          } finally {
706 <            lock.unlock();
706 >            lock.unlockWrite(stamp);
707          }
708 <        return (E)oldValue;
708 >        if (oobe)
709 >            throw new ArrayIndexOutOfBoundsException(index);
710 >        return oldValue;
711      }
712  
713      public int size() {
714 <        return count;
714 >        final StampedLock lock = this.lock;
715 >        long stamp = lock.tryOptimisticRead();
716 >        return count; // no need for validation
717 >    }
718 >
719 >    private int lockedSize() {
720 >        int n;
721 >        final StampedLock lock = this.lock;
722 >        long stamp = lock.readLock();
723 >        try {
724 >            n = count;
725 >        } finally {
726 >            lock.unlockRead(stamp);
727 >        }
728 >        return n;
729      }
730  
731      public List<E> subList(int fromIndex, int toIndex) {
795        int c = size();
732          int ssize = toIndex - fromIndex;
733 <        if (fromIndex < 0 || toIndex > c || ssize < 0)
734 <            throw new IndexOutOfBoundsException();
735 <        return new ReadMostlyVectorSublist<E>(this, fromIndex, ssize);
733 >        if (ssize >= 0 && fromIndex >= 0) {
734 >            ReadMostlyVectorSublist<E> ret = null;
735 >            final StampedLock lock = this.lock;
736 >            long stamp = lock.readLock();
737 >            try {
738 >                if (toIndex <= count)
739 >                    ret = new ReadMostlyVectorSublist<E>(this, fromIndex, ssize);
740 >            } finally {
741 >                lock.unlockRead(stamp);
742 >            }
743 >            if (ret != null)
744 >                return ret;
745 >        }
746 >
747 >        throw new ArrayIndexOutOfBoundsException(fromIndex < 0 ? fromIndex : toIndex);
748      }
749  
750      public Object[] toArray() {
751 <        return internalToArray(0, -1);
751 >        final StampedLock lock = this.lock;
752 >        long stamp = lock.readLock();
753 >        try {
754 >            return internalToArray(0, -1);
755 >        } finally {
756 >            lock.unlockRead(stamp);
757 >        }
758      }
759  
760      public <T> T[] toArray(T[] a) {
761 <        return internalToArray(a, 0, -1);
761 >        final StampedLock lock = this.lock;
762 >        long stamp = lock.readLock();
763 >        try {
764 >            return internalToArray(a, 0, -1);
765 >        } finally {
766 >            lock.unlockRead(stamp);
767 >        }
768      }
769  
770      public String toString() {
771 <        return internalToString(0, -1);
771 >        final StampedLock lock = this.lock;
772 >        long stamp = lock.readLock();
773 >        try {
774 >            return internalToString(0, -1);
775 >        } finally {
776 >            lock.unlockRead(stamp);
777 >        }
778      }
779  
780      // ReadMostlyVector-only methods
781  
782      /**
783 <     * Append the element if not present.
783 >     * Appends the element, if not present.
784       *
785       * @param e element to be added to this list, if absent
786       * @return {@code true} if the element was added
787       */
788      public boolean addIfAbsent(E e) {
789 <        boolean added;
790 <        SequenceLock lock = this.lock;
791 <        lock.lock();
789 >        boolean ret;
790 >        final StampedLock lock = this.lock;
791 >        long stamp = lock.writeLock();
792          try {
793 <            if (rawIndexOf(e, 0, count) < 0) {
793 >            if (findFirstIndex(array, e, 0, count) < 0) {
794                  rawAdd(e);
795 <                added = true;
795 >                ret = true;
796              }
797              else
798 <                added = false;
798 >                ret = false;
799          } finally {
800 <            lock.unlock();
800 >            lock.unlockWrite(stamp);
801          }
802 <        return added;
802 >        return ret;
803      }
804  
805      /**
# Line 852 | Line 818 | public class ReadMostlyVector<E> impleme
818          Object[] cs = c.toArray();
819          int clen = cs.length;
820          if (clen != 0) {
821 <            lock.lock();
821 >            long stamp = lock.writeLock();
822              try {
823                  for (int i = 0; i < clen; ++i) {
824 <                    Object e = cs[i];
825 <                    if (rawIndexOf(e, 0, count) < 0) {
824 >                    @SuppressWarnings("unchecked")
825 >                    E e = (E) cs[i];
826 >                    if (findFirstIndex(array, e, 0, count) < 0) {
827                          rawAdd(e);
828                          ++added;
829                      }
830                  }
831              } finally {
832 <                lock.unlock();
832 >                lock.unlockWrite(stamp);
833              }
834          }
835          return added;
# Line 881 | Line 848 | public class ReadMostlyVector<E> impleme
848      }
849  
850      static final class SnapshotIterator<E> implements Iterator<E> {
851 <        final Object[] items;
852 <        int cursor;
851 >        private final Object[] items;
852 >        private int cursor;
853          SnapshotIterator(ReadMostlyVector<E> v) { items = v.toArray(); }
854          public boolean hasNext() { return cursor < items.length; }
855 <        public E next() {
855 >        @SuppressWarnings("unchecked") public E next() {
856              if (cursor < items.length)
857                  return (E) items[cursor++];
858              throw new NoSuchElementException();
# Line 893 | Line 860 | public class ReadMostlyVector<E> impleme
860          public void remove() { throw new UnsupportedOperationException() ; }
861      }
862  
863 +    /** Interface describing a void action of one argument */
864 +    public interface Action<A> { void apply(A a); }
865 +
866 +    public void forEachReadOnly(Action<E> action) {
867 +        final StampedLock lock = this.lock;
868 +        long stamp = lock.readLock();
869 +        try {
870 +            Object[] items;
871 +            int len, n;
872 +            if ((items = array) != null && (len = items.length) > 0 &&
873 +                (n = count) <= len) {
874 +                for (int i = 0; i < n; ++i) {
875 +                    @SuppressWarnings("unchecked") E e = (E)items[i];
876 +                    action.apply(e);
877 +                }
878 +            }
879 +        } finally {
880 +            lock.unlockRead(stamp);
881 +        }
882 +    }
883 +
884      // Vector-only methods
885  
886      /** See {@link Vector#firstElement} */
887      public E firstElement() {
888 <        SequenceLock lock = this.lock;
889 <        for (;;) {
890 <            long seq = lock.awaitAvailability();
888 >        final StampedLock lock = this.lock;
889 >        long stamp = lock.tryOptimisticRead();
890 >        Object[] items;
891 >        if ((items = array) != null && count > 0 && items.length > 0) {
892 >            @SuppressWarnings("unchecked") E e = (E)items[0];
893 >            if (lock.validate(stamp))
894 >                return e;
895 >        }
896 >        return lockedFirstElement();
897 >    }
898 >
899 >    @SuppressWarnings("unchecked") private E lockedFirstElement() {
900 >        Object e = null;
901 >        boolean oobe = false;
902 >        final StampedLock lock = this.lock;
903 >        long stamp = lock.readLock();
904 >        try {
905              Object[] items = array;
906 <            int len = items.length;
905 <            int n = count;
906 <            if (n > len)
907 <                continue;
908 <            Object e; boolean ex;
909 <            if (n > 0) {
906 >            if (items != null && count > 0 && items.length > 0)
907                  e = items[0];
908 <                ex = false;
909 <            }
910 <            else {
911 <                e = null;
915 <                ex = true;
916 <            }
917 <            if (lock.getSequence() == seq) {
918 <                if (ex)
919 <                    throw new NoSuchElementException();
920 <                else
921 <                    return (E)e;
922 <            }
908 >            else
909 >                oobe = true;
910 >        } finally {
911 >            lock.unlockRead(stamp);
912          }
913 +        if (oobe)
914 +            throw new NoSuchElementException();
915 +        return (E) e;
916      }
917  
918      /** See {@link Vector#lastElement} */
919      public E lastElement() {
920 <        SequenceLock lock = this.lock;
921 <        for (;;) {
922 <            long seq = lock.awaitAvailability();
920 >        final StampedLock lock = this.lock;
921 >        long stamp = lock.tryOptimisticRead();
922 >        Object[] items;
923 >        int i;
924 >        if ((items = array) != null && (i = count - 1) >= 0 &&
925 >            i < items.length) {
926 >            @SuppressWarnings("unchecked") E e = (E)items[i];
927 >            if (lock.validate(stamp))
928 >                return e;
929 >        }
930 >        return lockedLastElement();
931 >    }
932 >
933 >    @SuppressWarnings("unchecked") private E lockedLastElement() {
934 >        Object e = null;
935 >        boolean oobe = false;
936 >        final StampedLock lock = this.lock;
937 >        long stamp = lock.readLock();
938 >        try {
939              Object[] items = array;
940 <            int len = items.length;
941 <            int n = count;
942 <            if (n > len)
943 <                continue;
944 <            Object e; boolean ex;
945 <            if (n > 0) {
946 <                e = items[n - 1];
939 <                ex = false;
940 <            }
941 <            else {
942 <                e = null;
943 <                ex = true;
944 <            }
945 <            if (lock.getSequence() == seq) {
946 <                if (ex)
947 <                    throw new NoSuchElementException();
948 <                else
949 <                    return (E)e;
950 <            }
940 >            int i = count - 1;
941 >            if (items != null && i >= 0 && i < items.length)
942 >                e = items[i];
943 >            else
944 >                oobe = true;
945 >        } finally {
946 >            lock.unlockRead(stamp);
947          }
948 +        if (oobe)
949 +            throw new NoSuchElementException();
950 +        return (E) e;
951      }
952  
953      /** See {@link Vector#indexOf(Object, int)} */
954      public int indexOf(Object o, int index) {
955 <        SequenceLock lock = this.lock;
957 <        int idx = 0;
958 <        boolean ex = false;
959 <        long seq = lock.awaitAvailability();
960 <        Object[] items = array;
961 <        int n = count;
962 <        boolean retry = false;
963 <        if (n > items.length)
964 <            retry = true;
965 <        else if (index < 0)
966 <            ex = true;
967 <        else
968 <            idx = validatedIndexOf(o, items, index, n, seq);
969 <        if (retry || lock.getSequence() != seq) {
970 <            lock.lock();
971 <            try {
972 <                if (index < 0)
973 <                    ex = true;
974 <                else
975 <                    idx = rawIndexOf(o, 0, count);
976 <            } finally {
977 <                lock.unlock();
978 <            }
979 <        }
980 <        if (ex)
955 >        if (index < 0)
956              throw new ArrayIndexOutOfBoundsException(index);
957 +        int idx;
958 +        final StampedLock lock = this.lock;
959 +        long stamp = lock.readLock();
960 +        try {
961 +            idx = findFirstIndex(array, o, index, count);
962 +        } finally {
963 +            lock.unlockRead(stamp);
964 +        }
965          return idx;
966      }
967  
968      /** See {@link Vector#lastIndexOf(Object, int)} */
969      public int lastIndexOf(Object o, int index) {
970 <        SequenceLock lock = this.lock;
971 <        int idx = 0;
972 <        boolean ex = false;
973 <        long seq = lock.awaitAvailability();
974 <        Object[] items = array;
975 <        int n = count;
976 <        boolean retry = false;
977 <        if (n > items.length)
978 <            retry = true;
979 <        else if (index >= n)
980 <            ex = true;
998 <        else
999 <            idx = validatedLastIndexOf(o, items, index, 0, seq);
1000 <        if (retry || lock.getSequence() != seq) {
1001 <            lock.lock();
1002 <            try {
1003 <                if (index >= count)
1004 <                    ex = true;
1005 <                else
1006 <                    idx = rawLastIndexOf(o, index, 0);
1007 <            } finally {
1008 <                lock.unlock();
1009 <            }
970 >        boolean oobe = false;
971 >        int idx = -1;
972 >        final StampedLock lock = this.lock;
973 >        long stamp = lock.readLock();
974 >        try {
975 >            if (index < count)
976 >                idx = findLastIndex(array, o, index, 0);
977 >            else
978 >                oobe = true;
979 >        } finally {
980 >            lock.unlockRead(stamp);
981          }
982 <        if (ex)
982 >        if (oobe)
983              throw new ArrayIndexOutOfBoundsException(index);
984          return idx;
985      }
# Line 1017 | Line 988 | public class ReadMostlyVector<E> impleme
988      public void setSize(int newSize) {
989          if (newSize < 0)
990              throw new ArrayIndexOutOfBoundsException(newSize);
991 <        SequenceLock lock = this.lock;
992 <        lock.lock();
991 >        final StampedLock lock = this.lock;
992 >        long stamp = lock.writeLock();
993          try {
994 +            Object[] items;
995              int n = count;
996              if (newSize > n)
997                  grow(newSize);
998 <            else {
1027 <                Object[] items = array;
998 >            else if ((items = array) != null) {
999                  for (int i = newSize ; i < n ; i++)
1000                      items[i] = null;
1001              }
1002              count = newSize;
1003          } finally {
1004 <            lock.unlock();
1004 >            lock.unlockWrite(stamp);
1005          }
1006      }
1007  
1008      /** See {@link Vector#copyInto} */
1009      public void copyInto(Object[] anArray) {
1010 <        SequenceLock lock = this.lock;
1011 <        lock.lock();
1010 >        final StampedLock lock = this.lock;
1011 >        long stamp = lock.writeLock();
1012          try {
1013 <            System.arraycopy(array, 0, anArray, 0, count);
1013 >            Object[] items;
1014 >            if ((items = array) != null)
1015 >                System.arraycopy(items, 0, anArray, 0, count);
1016          } finally {
1017 <            lock.unlock();
1017 >            lock.unlockWrite(stamp);
1018          }
1019      }
1020  
1021      /** See {@link Vector#trimToSize} */
1022      public void trimToSize() {
1023 <        SequenceLock lock = this.lock;
1024 <        lock.lock();
1023 >        final StampedLock lock = this.lock;
1024 >        long stamp = lock.writeLock();
1025          try {
1026              Object[] items = array;
1027              int n = count;
1028 <            if (n < items.length)
1028 >            if (items != null && n < items.length)
1029                  array = Arrays.copyOf(items, n);
1030          } finally {
1031 <            lock.unlock();
1031 >            lock.unlockWrite(stamp);
1032          }
1033      }
1034  
1035      /** See {@link Vector#ensureCapacity} */
1036      public void ensureCapacity(int minCapacity) {
1037          if (minCapacity > 0) {
1038 <            SequenceLock lock = this.lock;
1039 <            lock.lock();
1038 >            final StampedLock lock = this.lock;
1039 >            long stamp = lock.writeLock();
1040              try {
1041 <                if (minCapacity - array.length > 0)
1041 >                Object[] items = array;
1042 >                int cap = (items == null) ? 0 : items.length;
1043 >                if (minCapacity - cap > 0)
1044                      grow(minCapacity);
1045              } finally {
1046 <                lock.unlock();
1046 >                lock.unlockWrite(stamp);
1047              }
1048          }
1049      }
# Line 1121 | Line 1096 | public class ReadMostlyVector<E> impleme
1096      // other methods
1097  
1098      public ReadMostlyVector<E> clone() {
1124        SequenceLock lock = this.lock;
1099          Object[] a = null;
1100 <        boolean retry = false;
1101 <        long seq = lock.awaitAvailability();
1102 <        Object[] items = array;
1103 <        int n = count;
1104 <        if (n <= items.length)
1105 <            a = Arrays.copyOf(items, n);
1106 <        else
1107 <            retry = true;
1108 <        if (retry || lock.getSequence() != seq) {
1109 <            lock.lock();
1110 <            try {
1111 <                n = count;
1138 <                a = Arrays.copyOf(array, n);
1139 <            } finally {
1140 <                lock.unlock();
1100 >        int n;
1101 >        final StampedLock lock = this.lock;
1102 >        long stamp = lock.readLock();
1103 >        try {
1104 >            Object[] items = array;
1105 >            if (items == null)
1106 >                n = 0;
1107 >            else {
1108 >                int len = items.length;
1109 >                if ((n = count) > len)
1110 >                    n = len;
1111 >                a = Arrays.copyOf(items, n);
1112              }
1113 +        } finally {
1114 +            lock.unlockRead(stamp);
1115          }
1116          return new ReadMostlyVector<E>(a, n, capacityIncrement);
1117      }
1118  
1119      private void writeObject(java.io.ObjectOutputStream s)
1120 <            throws java.io.IOException {
1121 <        SequenceLock lock = this.lock;
1122 <        lock.lock();
1120 >        throws java.io.IOException {
1121 >        final StampedLock lock = this.lock;
1122 >        long stamp = lock.readLock();
1123          try {
1124              s.defaultWriteObject();
1125          } finally {
1126 <            lock.unlock();
1126 >            lock.unlockRead(stamp);
1127          }
1128      }
1129  
1130 <    static final class Itr<E> implements ListIterator<E>, Enumeration<E>  {
1130 >    static final class Itr<E> implements ListIterator<E>, Enumeration<E> {
1131 >        final StampedLock lock;
1132          final ReadMostlyVector<E> list;
1159        final SequenceLock lock;
1133          Object[] items;
1161        Object next, prev;
1134          long seq;
1135          int cursor;
1136          int fence;
1137          int lastRet;
1166        boolean validNext, validPrev;
1138  
1139          Itr(ReadMostlyVector<E> list, int index) {
1140 <            this.list = list;
1141 <            this.lock = list.lock;
1142 <            this.cursor = index;
1143 <            this.lastRet = -1;
1144 <            refresh();
1140 >            final StampedLock lock = list.lock;
1141 >            long stamp = lock.readLock();
1142 >            try {
1143 >                this.list = list;
1144 >                this.lock = lock;
1145 >                this.items = list.array;
1146 >                this.fence = list.count;
1147 >                this.cursor = index;
1148 >                this.lastRet = -1;
1149 >            } finally {
1150 >                this.seq = lock.tryConvertToOptimisticRead(stamp);
1151 >            }
1152              if (index < 0 || index > fence)
1153                  throw new ArrayIndexOutOfBoundsException(index);
1154          }
1155  
1156 <        private void refresh() {
1157 <            validNext = validPrev = false;
1180 <            do {
1181 <                seq = lock.awaitAvailability();
1182 <                items = list.array;
1183 <            } while ((fence = list.count) > items.length ||
1184 <                     lock.getSequence() != seq);
1156 >        public boolean hasPrevious() {
1157 >            return cursor > 0;
1158          }
1159  
1160 <        public boolean hasNext() {
1161 <            boolean valid;
1189 <            int i = cursor;
1190 <            for (;;) {
1191 <                if (i >= fence || i < 0 || i >= items.length) {
1192 <                    valid = false;
1193 <                    break;
1194 <                }
1195 <                next = items[i];
1196 <                if (lock.getSequence() == seq) {
1197 <                    valid = true;
1198 <                    break;
1199 <                }
1200 <                refresh();
1201 <            }
1202 <            return validNext = valid;
1160 >        public int nextIndex() {
1161 >            return cursor;
1162          }
1163  
1164 <        public boolean hasPrevious() {
1165 <            boolean valid;
1166 <            int i = cursor - 1;
1167 <            for (;;) {
1168 <                if (i >= fence || i < 0 || i >= items.length) {
1169 <                    valid = false;
1211 <                    break;
1212 <                }
1213 <                prev = items[i];
1214 <                if (lock.getSequence() == seq) {
1215 <                    valid = true;
1216 <                    break;
1217 <                }
1218 <                refresh();
1219 <            }
1220 <            return validPrev = valid;
1164 >        public int previousIndex() {
1165 >            return cursor - 1;
1166 >        }
1167 >
1168 >        public boolean hasNext() {
1169 >            return cursor < fence;
1170          }
1171  
1172          public E next() {
1173 <            if (validNext || hasNext()) {
1174 <                validNext = false;
1175 <                lastRet = cursor++;
1176 <                return (E) next;
1177 <            }
1178 <            throw new NoSuchElementException();
1173 >            int i = cursor;
1174 >            Object[] es = items;
1175 >            if (es == null || i < 0 || i >= fence || i >= es.length)
1176 >                throw new NoSuchElementException();
1177 >            @SuppressWarnings("unchecked") E e = (E)es[i];
1178 >            lastRet = i;
1179 >            cursor = i + 1;
1180 >            if (!lock.validate(seq))
1181 >                throw new ConcurrentModificationException();
1182 >            return e;
1183          }
1184  
1185          public E previous() {
1186 <            if (validPrev || hasPrevious()) {
1187 <                validPrev = false;
1188 <                lastRet = cursor--;
1189 <                return (E) prev;
1190 <            }
1191 <            throw new NoSuchElementException();
1186 >            int i = cursor - 1;
1187 >            Object[] es = items;
1188 >            if (es == null || i < 0 || i >= fence || i >= es.length)
1189 >                throw new NoSuchElementException();
1190 >            @SuppressWarnings("unchecked") E e = (E)es[i];
1191 >            lastRet = i;
1192 >            cursor = i;
1193 >            if (!lock.validate(seq))
1194 >                throw new ConcurrentModificationException();
1195 >            return e;
1196          }
1197  
1198          public void remove() {
1199              int i = lastRet;
1200              if (i < 0)
1201                  throw new IllegalStateException();
1202 <            lock.lock();
1202 >            if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1203 >                throw new ConcurrentModificationException();
1204              try {
1205 <                if (i < list.count)
1206 <                    list.remove(i);
1205 >                list.rawRemoveAt(i);
1206 >                fence = list.count;
1207 >                cursor = i;
1208 >                lastRet = -1;
1209              } finally {
1210 <                lock.unlock();
1210 >                seq = lock.tryConvertToOptimisticRead(seq);
1211              }
1252            cursor = i;
1253            lastRet = -1;
1254            refresh();
1212          }
1213  
1214          public void set(E e) {
1215              int i = lastRet;
1216 <            if (i < 0)
1216 >            Object[] es = items;
1217 >            if (es == null || i < 0 | i >= fence)
1218                  throw new IllegalStateException();
1219 <            lock.lock();
1219 >            if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1220 >                throw new ConcurrentModificationException();
1221              try {
1222 <                if (i < list.count)
1264 <                    list.set(i, e);
1222 >                es[i] = e;
1223              } finally {
1224 <                lock.unlock();
1224 >                seq = lock.tryConvertToOptimisticRead(seq);
1225              }
1268            refresh();
1226          }
1227  
1228          public void add(E e) {
1229              int i = cursor;
1230              if (i < 0)
1231                  throw new IllegalStateException();
1232 <            lock.lock();
1232 >            if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1233 >                throw new ConcurrentModificationException();
1234              try {
1235 <                if (i <= list.count)
1236 <                    list.add(i, e);
1235 >                list.rawAddAt(i, e);
1236 >                items = list.array;
1237 >                fence = list.count;
1238 >                cursor = i + 1;
1239 >                lastRet = -1;
1240              } finally {
1241 <                lock.unlock();
1241 >                seq = lock.tryConvertToOptimisticRead(seq);
1242              }
1282            cursor = i + 1;
1283            lastRet = -1;
1284            refresh();
1243          }
1244  
1245          public boolean hasMoreElements() { return hasNext(); }
1246          public E nextElement() { return next(); }
1289        public int nextIndex() { return cursor; }
1290        public int previousIndex() { return cursor - 1; }
1247      }
1248  
1249 <    static final class ReadMostlyVectorSublist<E> implements List<E>, RandomAccess, java.io.Serializable {
1249 >    static final class ReadMostlyVectorSublist<E>
1250 >            implements List<E>, RandomAccess, java.io.Serializable {
1251 >        static final long serialVersionUID = 3041673470172026059L;
1252 >
1253          final ReadMostlyVector<E> list;
1254          final int offset;
1255          volatile int size;
1256  
1257 <        ReadMostlyVectorSublist(ReadMostlyVector<E> list, int offset, int size) {
1257 >        ReadMostlyVectorSublist(ReadMostlyVector<E> list,
1258 >                                int offset, int size) {
1259              this.list = list;
1260              this.offset = offset;
1261              this.size = size;
# Line 1307 | Line 1267 | public class ReadMostlyVector<E> impleme
1267          }
1268  
1269          public boolean add(E element) {
1270 <            SequenceLock lock = list.lock;
1271 <            lock.lock();
1270 >            final StampedLock lock = list.lock;
1271 >            long stamp = lock.writeLock();
1272              try {
1273                  int c = size;
1274                  list.rawAddAt(c + offset, element);
1275                  size = c + 1;
1276              } finally {
1277 <                lock.unlock();
1277 >                lock.unlockWrite(stamp);
1278              }
1279              return true;
1280          }
1281  
1282          public void add(int index, E element) {
1283 <            SequenceLock lock = list.lock;
1284 <            lock.lock();
1283 >            final StampedLock lock = list.lock;
1284 >            long stamp = lock.writeLock();
1285              try {
1286                  if (index < 0 || index > size)
1287                      throw new ArrayIndexOutOfBoundsException(index);
1288                  list.rawAddAt(index + offset, element);
1289                  ++size;
1290              } finally {
1291 <                lock.unlock();
1291 >                lock.unlockWrite(stamp);
1292              }
1293          }
1294  
1295          public boolean addAll(Collection<? extends E> c) {
1296              Object[] elements = c.toArray();
1297 <            int added;
1298 <            SequenceLock lock = list.lock;
1339 <            lock.lock();
1297 >            final StampedLock lock = list.lock;
1298 >            long stamp = lock.writeLock();
1299              try {
1300                  int s = size;
1301                  int pc = list.count;
1302                  list.rawAddAllAt(offset + s, elements);
1303 <                added = list.count - pc;
1303 >                int added = list.count - pc;
1304                  size = s + added;
1305 +                return added != 0;
1306              } finally {
1307 <                lock.unlock();
1307 >                lock.unlockWrite(stamp);
1308              }
1349            return added != 0;
1309          }
1310  
1311          public boolean addAll(int index, Collection<? extends E> c) {
1312              Object[] elements = c.toArray();
1313 <            int added;
1314 <            SequenceLock lock = list.lock;
1356 <            lock.lock();
1313 >            final StampedLock lock = list.lock;
1314 >            long stamp = lock.writeLock();
1315              try {
1316                  int s = size;
1317                  if (index < 0 || index > s)
1318                      throw new ArrayIndexOutOfBoundsException(index);
1319                  int pc = list.count;
1320                  list.rawAddAllAt(index + offset, elements);
1321 <                added = list.count - pc;
1321 >                int added = list.count - pc;
1322                  size = s + added;
1323 +                return added != 0;
1324              } finally {
1325 <                lock.unlock();
1325 >                lock.unlockWrite(stamp);
1326              }
1368            return added != 0;
1327          }
1328  
1329          public void clear() {
1330 <            SequenceLock lock = list.lock;
1331 <            lock.lock();
1330 >            final StampedLock lock = list.lock;
1331 >            long stamp = lock.writeLock();
1332              try {
1333                  list.internalClear(offset, offset + size);
1334                  size = 0;
1335              } finally {
1336 <                lock.unlock();
1336 >                lock.unlockWrite(stamp);
1337              }
1338          }
1339  
# Line 1384 | Line 1342 | public class ReadMostlyVector<E> impleme
1342          }
1343  
1344          public boolean containsAll(Collection<?> c) {
1345 <            return list.internalContainsAll(c, offset, offset + size);
1345 >            final StampedLock lock = list.lock;
1346 >            long stamp = lock.readLock();
1347 >            try {
1348 >                return list.internalContainsAll(c, offset, offset + size);
1349 >            } finally {
1350 >                lock.unlockRead(stamp);
1351 >            }
1352          }
1353  
1354          public boolean equals(Object o) {
# Line 1392 | Line 1356 | public class ReadMostlyVector<E> impleme
1356                  return true;
1357              if (!(o instanceof List))
1358                  return false;
1359 <            return list.internalEquals((List<?>)(o), offset, offset + size);
1359 >            final StampedLock lock = list.lock;
1360 >            long stamp = lock.readLock();
1361 >            try {
1362 >                return list.internalEquals((List<?>)(o), offset, offset + size);
1363 >            } finally {
1364 >                lock.unlockRead(stamp);
1365 >            }
1366          }
1367  
1368          public E get(int index) {
# Line 1402 | Line 1372 | public class ReadMostlyVector<E> impleme
1372          }
1373  
1374          public int hashCode() {
1375 <            return list.internalHashCode(offset, offset + size);
1375 >            final StampedLock lock = list.lock;
1376 >            long stamp = lock.readLock();
1377 >            try {
1378 >                return list.internalHashCode(offset, offset + size);
1379 >            } finally {
1380 >                lock.unlockRead(stamp);
1381 >            }
1382          }
1383  
1384          public int indexOf(Object o) {
1385 <            SequenceLock lock = list.lock;
1386 <            long seq = lock.awaitAvailability();
1411 <            Object[] items = list.array;
1412 <            int c = list.count;
1413 <            if (c <= items.length) {
1414 <                int idx = list.validatedIndexOf(o, items, offset,
1415 <                                                offset + size, seq);
1416 <                if (lock.getSequence() == seq)
1417 <                    return idx < 0 ? -1 : idx - offset;
1418 <            }
1419 <            lock.lock();
1385 >            final StampedLock lock = list.lock;
1386 >            long stamp = lock.readLock();
1387              try {
1388 <                int idx = list.rawIndexOf(o, offset, offset + size);
1388 >                int idx = findFirstIndex(list.array, o, offset, offset + size);
1389                  return idx < 0 ? -1 : idx - offset;
1390              } finally {
1391 <                lock.unlock();
1391 >                lock.unlockRead(stamp);
1392              }
1393          }
1394  
1395          public boolean isEmpty() {
1396 <            return size == 0;
1396 >            return size() == 0;
1397          }
1398  
1399          public Iterator<E> iterator() {
# Line 1434 | Line 1401 | public class ReadMostlyVector<E> impleme
1401          }
1402  
1403          public int lastIndexOf(Object o) {
1404 <            SequenceLock lock = list.lock;
1405 <            long seq = lock.awaitAvailability();
1439 <            Object[] items = list.array;
1440 <            int c = list.count;
1441 <            if (c <= items.length) {
1442 <                int idx = list.validatedLastIndexOf(o, items, offset+size-1,
1443 <                                                    offset, seq);
1444 <                if (lock.getSequence() == seq)
1445 <                    return idx < 0 ? -1 : idx - offset;
1446 <            }
1447 <            lock.lock();
1404 >            final StampedLock lock = list.lock;
1405 >            long stamp = lock.readLock();
1406              try {
1407 <                int idx = list.rawLastIndexOf(o, offset + size - 1, offset);
1407 >                int idx = findLastIndex(list.array, o, offset + size - 1, offset);
1408                  return idx < 0 ? -1 : idx - offset;
1409              } finally {
1410 <                lock.unlock();
1410 >                lock.unlockRead(stamp);
1411              }
1412          }
1413  
# Line 1462 | Line 1420 | public class ReadMostlyVector<E> impleme
1420          }
1421  
1422          public E remove(int index) {
1423 <            Object result;
1424 <            SequenceLock lock = list.lock;
1467 <            lock.lock();
1423 >            final StampedLock lock = list.lock;
1424 >            long stamp = lock.writeLock();
1425              try {
1426                  Object[] items = list.array;
1427                  int i = index + offset;
1428 <                if (index < 0 || index >= size || i >= items.length)
1428 >                if (items == null || index < 0 || index >= size || i >= items.length)
1429                      throw new ArrayIndexOutOfBoundsException(index);
1430 <                result = items[i];
1430 >                @SuppressWarnings("unchecked") E result = (E)items[i];
1431                  list.rawRemoveAt(i);
1432                  size--;
1433 +                return result;
1434              } finally {
1435 <                lock.unlock();
1435 >                lock.unlockWrite(stamp);
1436              }
1479            return (E)result;
1437          }
1438  
1439          public boolean remove(Object o) {
1440 <            boolean removed = false;
1441 <            SequenceLock lock = list.lock;
1442 <            lock.lock();
1443 <            try {
1444 <                if (list.rawRemoveAt(list.rawIndexOf(o, offset,
1488 <                                                     offset + size))) {
1489 <                    removed = true;
1440 >            final StampedLock lock = list.lock;
1441 >            long stamp = lock.writeLock();
1442 >            try {
1443 >                if (list.rawRemoveAt(findFirstIndex(list.array, o, offset,
1444 >                                                    offset + size))) {
1445                      --size;
1446 +                    return true;
1447                  }
1448 +                else
1449 +                    return false;
1450              } finally {
1451 <                lock.unlock();
1451 >                lock.unlockWrite(stamp);
1452              }
1495            return removed;
1453          }
1454  
1455          public boolean removeAll(Collection<?> c) {
1456 <            return list.internalRemoveAll(c, offset, offset + size);
1456 >            return list.lockedRemoveAll(c, offset, offset + size);
1457          }
1458  
1459          public boolean retainAll(Collection<?> c) {
1460 <            return list.internalRetainAll(c, offset, offset + size);
1460 >            return list.lockedRetainAll(c, offset, offset + size);
1461          }
1462  
1463          public E set(int index, E element) {
# Line 1516 | Line 1473 | public class ReadMostlyVector<E> impleme
1473          public List<E> subList(int fromIndex, int toIndex) {
1474              int c = size;
1475              int ssize = toIndex - fromIndex;
1476 <            if (fromIndex < 0 || toIndex > c || ssize < 0)
1477 <                throw new IndexOutOfBoundsException();
1476 >            if (fromIndex < 0)
1477 >                throw new ArrayIndexOutOfBoundsException(fromIndex);
1478 >            if (toIndex > c || ssize < 0)
1479 >                throw new ArrayIndexOutOfBoundsException(toIndex);
1480              return new ReadMostlyVectorSublist<E>(list, offset+fromIndex, ssize);
1481          }
1482  
1483          public Object[] toArray() {
1484 <            return list.internalToArray(offset, offset + size);
1484 >            final StampedLock lock = list.lock;
1485 >            long stamp = lock.readLock();
1486 >            try {
1487 >                return list.internalToArray(offset, offset + size);
1488 >            } finally {
1489 >                lock.unlockRead(stamp);
1490 >            }
1491          }
1492  
1493          public <T> T[] toArray(T[] a) {
1494 <            return list.internalToArray(a, offset, offset + size);
1494 >            final StampedLock lock = list.lock;
1495 >            long stamp = lock.readLock();
1496 >            try {
1497 >                return list.internalToArray(a, offset, offset + size);
1498 >            } finally {
1499 >                lock.unlockRead(stamp);
1500 >            }
1501          }
1502  
1503          public String toString() {
1504 <            return list.internalToString(offset, offset + size);
1504 >            final StampedLock lock = list.lock;
1505 >            long stamp = lock.readLock();
1506 >            try {
1507 >                return list.internalToString(offset, offset + size);
1508 >            } finally {
1509 >                lock.unlockRead(stamp);
1510 >            }
1511          }
1512  
1513      }
# Line 1538 | Line 1515 | public class ReadMostlyVector<E> impleme
1515      static final class SubItr<E> implements ListIterator<E> {
1516          final ReadMostlyVectorSublist<E> sublist;
1517          final ReadMostlyVector<E> list;
1518 <        final SequenceLock lock;
1518 >        final StampedLock lock;
1519          Object[] items;
1543        Object next, prev;
1520          long seq;
1521          int cursor;
1522 +        int origin;
1523          int fence;
1524          int lastRet;
1548        boolean validNext, validPrev;
1525  
1526          SubItr(ReadMostlyVectorSublist<E> sublist, int index) {
1527 <            this.sublist = sublist;
1528 <            this.list = sublist.list;
1529 <            this.lock = list.lock;
1530 <            this.cursor = index;
1531 <            this.lastRet = -1;
1532 <            refresh();
1533 <            if (index < 0 || index > fence)
1527 >            final StampedLock lock = sublist.list.lock;
1528 >            long stamp = lock.readLock();
1529 >            try {
1530 >                this.sublist = sublist;
1531 >                this.list = sublist.list;
1532 >                this.lock = lock;
1533 >                this.cursor = index;
1534 >                this.origin = sublist.offset;
1535 >                this.fence = origin + sublist.size;
1536 >                this.lastRet = -1;
1537 >            } finally {
1538 >                this.seq = lock.tryConvertToOptimisticRead(stamp);
1539 >            }
1540 >            if (index < 0 || cursor > fence)
1541                  throw new ArrayIndexOutOfBoundsException(index);
1542          }
1543  
1544 <        private void refresh() {
1545 <            validNext = validPrev = false;
1546 <            do {
1547 <                int n;
1548 <                seq = lock.awaitAvailability();
1549 <                items = list.array;
1567 <                if ((n = list.count) > items.length)
1568 <                    continue;
1569 <                int b = sublist.offset + sublist.size;
1570 <                fence = b < n ? b : n;
1571 <            } while (lock.getSequence() != seq);
1544 >        public int nextIndex() {
1545 >            return cursor - origin;
1546 >        }
1547 >
1548 >        public int previousIndex() {
1549 >            return cursor - origin - 1;
1550          }
1551  
1552          public boolean hasNext() {
1553 <            boolean valid;
1576 <            int i = cursor;
1577 <            for (;;) {
1578 <                if (i >= fence || i < 0 || i >= items.length) {
1579 <                    valid = false;
1580 <                    break;
1581 <                }
1582 <                next = items[i];
1583 <                if (lock.getSequence() == seq) {
1584 <                    valid = true;
1585 <                    break;
1586 <                }
1587 <                refresh();
1588 <            }
1589 <            return validNext = valid;
1553 >            return cursor < fence;
1554          }
1555  
1556          public boolean hasPrevious() {
1557 <            boolean valid;
1594 <            int i = cursor - 1;
1595 <            for (;;) {
1596 <                if (i >= fence || i < 0 || i >= items.length) {
1597 <                    valid = false;
1598 <                    break;
1599 <                }
1600 <                prev = items[i];
1601 <                if (lock.getSequence() == seq) {
1602 <                    valid = true;
1603 <                    break;
1604 <                }
1605 <                refresh();
1606 <            }
1607 <            return validPrev = valid;
1557 >            return cursor > origin;
1558          }
1559  
1560          public E next() {
1561 <            if (validNext || hasNext()) {
1562 <                validNext = false;
1563 <                lastRet = cursor++;
1564 <                return (E) next;
1565 <            }
1566 <            throw new NoSuchElementException();
1561 >            int i = cursor;
1562 >            Object[] es = items;
1563 >            if (es == null || i < origin || i >= fence || i >= es.length)
1564 >                throw new NoSuchElementException();
1565 >            @SuppressWarnings("unchecked") E e = (E)es[i];
1566 >            lastRet = i;
1567 >            cursor = i + 1;
1568 >            if (!lock.validate(seq))
1569 >                throw new ConcurrentModificationException();
1570 >            return e;
1571          }
1572  
1573          public E previous() {
1574 <            if (validPrev || hasPrevious()) {
1575 <                validPrev = false;
1576 <                lastRet = cursor--;
1577 <                return (E) prev;
1578 <            }
1579 <            throw new NoSuchElementException();
1580 <        }
1581 <
1582 <        public int nextIndex() {
1583 <            return cursor - sublist.offset;
1630 <        }
1631 <
1632 <        public int previousIndex() {
1633 <            return cursor - 1 - sublist.offset;
1574 >            int i = cursor - 1;
1575 >            Object[] es = items;
1576 >            if (es == null || i < 0 || i >= fence || i >= es.length)
1577 >                throw new NoSuchElementException();
1578 >            @SuppressWarnings("unchecked") E e = (E)es[i];
1579 >            lastRet = i;
1580 >            cursor = i;
1581 >            if (!lock.validate(seq))
1582 >                throw new ConcurrentModificationException();
1583 >            return e;
1584          }
1585  
1586          public void remove() {
1587              int i = lastRet;
1588              if (i < 0)
1589                  throw new IllegalStateException();
1590 <            cursor = i;
1591 <            lastRet = -1;
1642 <            lock.lock();
1590 >            if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1591 >                throw new ConcurrentModificationException();
1592              try {
1593 <                if (i < list.count) {
1594 <                    list.remove(i);
1595 <                    --sublist.size;
1596 <                }
1593 >                list.rawRemoveAt(i);
1594 >                fence = origin + sublist.size;
1595 >                cursor = i;
1596 >                lastRet = -1;
1597              } finally {
1598 <                lock.unlock();
1598 >                seq = lock.tryConvertToOptimisticRead(seq);
1599              }
1651            refresh();
1600          }
1601  
1602          public void set(E e) {
1603              int i = lastRet;
1604 <            if (i < 0)
1604 >            if (i < origin || i >= fence)
1605                  throw new IllegalStateException();
1606 <            lock.lock();
1606 >            if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1607 >                throw new ConcurrentModificationException();
1608              try {
1609 <                if (i < list.count)
1661 <                    list.set(i, e);
1609 >                list.set(i, e);
1610              } finally {
1611 <                lock.unlock();
1611 >                seq = lock.tryConvertToOptimisticRead(seq);
1612              }
1665            refresh();
1613          }
1614  
1615          public void add(E e) {
1616              int i = cursor;
1617 <            if (i < 0)
1617 >            if (i < origin || i >= fence)
1618                  throw new IllegalStateException();
1619 <            cursor = i + 1;
1620 <            lastRet = -1;
1674 <            lock.lock();
1619 >            if ((seq = lock.tryConvertToWriteLock(seq)) == 0)
1620 >                throw new ConcurrentModificationException();
1621              try {
1622 <                if (i <= list.count) {
1623 <                    list.add(i, e);
1624 <                    ++sublist.size;
1625 <                }
1622 >                list.rawAddAt(i, e);
1623 >                items = list.array;
1624 >                fence = origin + sublist.size;
1625 >                cursor = i + 1;
1626 >                lastRet = -1;
1627              } finally {
1628 <                lock.unlock();
1628 >                seq = lock.tryConvertToOptimisticRead(seq);
1629              }
1683            refresh();
1630          }
1685
1631      }
1632   }
1688

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines