--- jsr166/src/jsr166e/extra/ReadMostlyVector.java 2011/12/04 01:25:16 1.14 +++ jsr166/src/jsr166e/extra/ReadMostlyVector.java 2011/12/31 22:50:51 1.23 @@ -49,6 +49,11 @@ public class ReadMostlyVector * read-only mode, and then lock. When in read-only mode, they * validate only at the end of an array scan unless the element is * actually used (for example, as an argument of method equals). + * + * We rely on some invariants that are always true, even for field + * reads in read-only mode that have not yet been validated: + * - array != null + * - count >= 0 */ /** @@ -155,7 +160,11 @@ public class ReadMostlyVector * as well as sublist and iterator classes. */ - // Version of indexOf that returns -1 if either not present or invalid + /** + * Version of indexOf that returns -1 if either not present or invalid. + * + * @throws ArrayIndexOutOfBoundsException if index is negative + */ final int validatedIndexOf(Object x, Object[] items, int index, int fence, long seq) { for (int i = index; i < fence; ++i) { @@ -168,6 +177,9 @@ public class ReadMostlyVector return -1; } + /** + * @throws ArrayIndexOutOfBoundsException if index is negative + */ final int rawIndexOf(Object x, int index, int fence) { Object[] items = array; for (int i = index; i < fence; ++i) { @@ -648,16 +660,12 @@ public class ReadMostlyVector long seq = lock.awaitAvailability(); int n = count; Object[] items = array; - if (n > items.length) - continue; - boolean outOfBounds = (index < 0 || index >= n); @SuppressWarnings("unchecked") - E e = outOfBounds ? null : (E) items[index]; + E e = (index < items.length) ? (E) items[index] : null; if (lock.getSequence() == seq) { - if (outOfBounds) + if (index >= n) throw new ArrayIndexOutOfBoundsException(index); - else - return e; + return e; } } } @@ -667,28 +675,7 @@ public class ReadMostlyVector } public int indexOf(Object o) { - final SequenceLock lock = this.lock; - for (;;) { - long seq = lock.awaitAvailability(); - Object[] items = array; - int n = count; - if (n <= items.length) { - for (int i = 0; i < n; ++i) { - Object e = items[i]; - if (lock.getSequence() != seq) { - lock.lock(); - try { - return rawIndexOf(o, 0, count); - } finally { - lock.unlock(); - } - } - else if ((o == null) ? e == null : o.equals(e)) - return i; - } - return -1; - } - } + return indexOf(o, 0); } public boolean isEmpty() { @@ -711,7 +698,7 @@ public class ReadMostlyVector if (lock.getSequence() != seq) { lock.lock(); try { - return rawLastIndexOf(o, 0, count); + return rawLastIndexOf(o, count - 1, 0); } finally { lock.unlock(); } @@ -895,18 +882,13 @@ public class ReadMostlyVector for (;;) { long seq = lock.awaitAvailability(); Object[] items = array; - int len = items.length; int n = count; - if (n > len) - continue; - boolean empty = (n == 0); @SuppressWarnings("unchecked") - E e = empty ? null : (E) items[0]; + E e = (items.length > 0) ? (E) items[0] : null; if (lock.getSequence() == seq) { - if (empty) + if (n <= 0) throw new NoSuchElementException(); - else - return e; + return e; } } } @@ -917,18 +899,13 @@ public class ReadMostlyVector for (;;) { long seq = lock.awaitAvailability(); Object[] items = array; - int len = items.length; int n = count; - if (n > len) - continue; - boolean empty = (n == 0); @SuppressWarnings("unchecked") - E e = empty ? null : (E) items[n - 1]; + E e = (n > 0 && items.length >= n) ? (E) items[n - 1] : null; if (lock.getSequence() == seq) { - if (empty) + if (n <= 0) throw new NoSuchElementException(); - else - return e; + return e; } } } @@ -936,62 +913,45 @@ public class ReadMostlyVector /** See {@link Vector#indexOf(Object, int)} */ public int indexOf(Object o, int index) { final SequenceLock lock = this.lock; - int idx = 0; - boolean ex = false; long seq = lock.awaitAvailability(); Object[] items = array; int n = count; - boolean retry = false; - if (n > items.length) - retry = true; - else if (index < 0) - ex = true; - else + int idx = -1; + if (n <= items.length) idx = validatedIndexOf(o, items, index, n, seq); - if (retry || lock.getSequence() != seq) { + if (lock.getSequence() != seq) { lock.lock(); try { - if (index < 0) - ex = true; - else - idx = rawIndexOf(o, 0, count); + idx = rawIndexOf(o, index, count); } finally { lock.unlock(); } } - if (ex) - throw new ArrayIndexOutOfBoundsException(index); + // Above code will throw AIOOBE when index < 0 return idx; } /** See {@link Vector#lastIndexOf(Object, int)} */ public int lastIndexOf(Object o, int index) { final SequenceLock lock = this.lock; - int idx = 0; - boolean ex = false; long seq = lock.awaitAvailability(); Object[] items = array; int n = count; - boolean retry = false; - if (n > items.length) - retry = true; - else if (index >= n) - ex = true; - else + int idx = -1; + if (index < Math.min(n, items.length)) idx = validatedLastIndexOf(o, items, index, 0, seq); - if (retry || lock.getSequence() != seq) { + if (lock.getSequence() != seq) { lock.lock(); try { - if (index >= count) - ex = true; - else + n = count; + if (index < n) idx = rawLastIndexOf(o, index, 0); } finally { lock.unlock(); } } - if (ex) - throw new ArrayIndexOutOfBoundsException(index); + if (index >= n) + throw new IndexOutOfBoundsException(index + " >= " + n); return idx; } @@ -1136,7 +1096,7 @@ public class ReadMostlyVector } } - static final class Itr implements ListIterator, Enumeration { + static final class Itr implements ListIterator, Enumeration { final ReadMostlyVector list; final SequenceLock lock; Object[] items;