--- jsr166/src/jsr166e/extra/ReadMostlyVector.java 2011/12/31 05:50:22 1.18 +++ jsr166/src/jsr166e/extra/ReadMostlyVector.java 2012/02/21 01:54:03 1.25 @@ -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 */ /** @@ -57,7 +62,7 @@ public class ReadMostlyVector */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; - // fields are non-private to simpify nested class access + // fields are non-private to simplify nested class access volatile Object[] array; final SequenceLock lock; volatile int count; @@ -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) { @@ -686,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(); } @@ -783,7 +795,7 @@ public class ReadMostlyVector // ReadMostlyVector-only methods /** - * Append the element if not present. + * Appends the element, if not present. * * @param e element to be added to this list, if absent * @return {@code true} if the element was added @@ -870,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; } } } @@ -892,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; } } } @@ -911,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, index, 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; }