--- jsr166/src/jsr166e/extra/ReadMostlyVector.java 2011/07/15 23:56:18 1.1
+++ jsr166/src/jsr166e/extra/ReadMostlyVector.java 2012/08/13 11:20:39 1.27
@@ -9,18 +9,20 @@ import jsr166e.*;
import java.util.*;
/**
- * A class with the same API and array-based characteristics as {@link
- * java.util.Vector} but with reduced contention and improved
+ * A class with the same methods and array-based characteristics as
+ * {@link java.util.Vector} but with reduced contention and improved
* throughput when invocations of read-only methods by multiple
- * threads are most common. Instances of this class may have
- * relatively poorer performance in other contexts.
+ * threads are most common.
*
*
The iterators returned by this class's {@link #iterator()
* iterator} and {@link #listIterator(int) listIterator} methods are
* best-effort in the presence of concurrent modifications, and do
* NOT throw {@link ConcurrentModificationException}. An
* iterator's {@code next()} method returns consecutive elements as
- * they appear in the underlying array upon each access.
+ * they appear in the underlying array upon each access. Alternatively,
+ * method {@link #snapshotIterator} may be used for deterministic
+ * traversals, at the expense of making a copy, and unavailability of
+ * method {@code Iterator.remove}.
*
*
Otherwise, this class supports all methods, under the same
* documented specifications, as {@code Vector}. Consult {@link
@@ -30,13 +32,28 @@ import java.util.*;
*
* @author Doug Lea
*/
-public class ReadMostlyVector implements List, RandomAccess, Cloneable, java.io.Serializable {
+public class ReadMostlyVector
+ implements List, RandomAccess, Cloneable, java.io.Serializable {
private static final long serialVersionUID = 8673264195747942595L;
/*
* This class exists mainly as a vehicle to exercise various
- * constructions using SequenceLocks, which are not yet explained
- * well here.
+ * constructions using SequenceLocks. Read-only methods
+ * take one of a few forms:
+ *
+ * Short methods,including get(index), continually retry obtaining
+ * a snapshot of array, count, and element, using sequence number
+ * to validate.
+ *
+ * Methods that are potentially O(n) (or worse) try once in
+ * 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
*/
/**
@@ -45,10 +62,10 @@ public class ReadMostlyVector impleme
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
- // fields are non-private to simpify nested class access
- Object[] array;
+ // fields are non-private to simplify nested class access
+ volatile Object[] array;
final SequenceLock lock;
- int count;
+ volatile int count;
final int capacityIncrement;
/**
@@ -118,7 +135,7 @@ public class ReadMostlyVector impleme
}
// For explanation, see CopyOnWriteArrayList
- final void grow(int minCapacity) {
+ final Object[] grow(int minCapacity) {
int oldCapacity = array.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
@@ -126,7 +143,7 @@ public class ReadMostlyVector impleme
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
- array = Arrays.copyOf(array, newCapacity);
+ return array = Arrays.copyOf(array, newCapacity);
}
static int hugeCapacity(int minCapacity) {
@@ -143,94 +160,129 @@ public class ReadMostlyVector impleme
* as well as sublist and iterator classes.
*/
- static int internalIndexOf(Object o, Object[] items,
- int index, int fence) {
+ /**
+ * 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) {
+ Object e = items[i];
+ if (lock.getSequence() != seq)
+ break;
+ if ((x == null) ? e == null : x.equals(e))
+ return i;
+ }
+ 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) {
- Object x = items[i];
- if (o == null? x == null : (x != null && o.equals(x)))
+ Object e = items[i];
+ if ((x == null) ? e == null : x.equals(e))
return i;
}
return -1;
}
- static int internalLastIndexOf(Object o, Object[] items,
- int index, int origin) {
+ final int validatedLastIndexOf(Object x, Object[] items,
+ int index, int origin, long seq) {
for (int i = index; i >= origin; --i) {
- Object x = items[i];
- if (o == null? x == null : (x != null && o.equals(x)))
+ Object e = items[i];
+ if (lock.getSequence() != seq)
+ break;
+ if ((x == null) ? e == null : x.equals(e))
return i;
}
return -1;
}
- final void internalAdd(E e) {
- int c = count;
- if (c >= array.length)
- grow(c + 1);
- array[c] = e;
- count = c + 1;
+ final int rawLastIndexOf(Object x, int index, int origin) {
+ Object[] items = array;
+ for (int i = index; i >= origin; --i) {
+ Object e = items[i];
+ if ((x == null) ? e == null : x.equals(e))
+ return i;
+ }
+ return -1;
}
- final void internalAddAt(int index, E e) {
- int c = count;
- if (index > c)
+ final void rawAdd(E e) {
+ int n = count;
+ Object[] items = array;
+ if (n >= items.length)
+ items = grow(n + 1);
+ items[n] = e;
+ count = n + 1;
+ }
+
+ final void rawAddAt(int index, E e) {
+ int n = count;
+ Object[] items = array;
+ if (index > n)
throw new ArrayIndexOutOfBoundsException(index);
- if (c >= array.length)
- grow(c + 1);
- System.arraycopy(array, index, array, index + 1, c - index);
- array[index] = e;
- count = c + 1;
+ if (n >= items.length)
+ items = grow(n + 1);
+ if (index < n)
+ System.arraycopy(items, index, items, index + 1, n - index);
+ items[index] = e;
+ count = n + 1;
}
- final boolean internalAddAllAt(int index, Object[] elements) {
- int c = count;
- if (index < 0 || index > c)
+ final boolean rawAddAllAt(int index, Object[] elements) {
+ int n = count;
+ Object[] items = array;
+ if (index < 0 || index > n)
throw new ArrayIndexOutOfBoundsException(index);
int len = elements.length;
if (len == 0)
return false;
- int newCount = c + len;
- if (newCount >= array.length)
- grow(newCount);
- int mv = count - index;
+ int newCount = n + len;
+ if (newCount >= items.length)
+ items = grow(newCount);
+ int mv = n - index;
if (mv > 0)
- System.arraycopy(array, index, array, index + len, mv);
- System.arraycopy(elements, 0, array, index, len);
+ System.arraycopy(items, index, items, index + len, mv);
+ System.arraycopy(elements, 0, items, index, len);
count = newCount;
return true;
}
- final boolean internalRemoveAt(int index) {
- int c = count - 1;
- if (index < 0 || index > c)
+ final boolean rawRemoveAt(int index) {
+ int n = count - 1;
+ Object[] items = array;
+ if (index < 0 || index > n)
return false;
- int mv = c - index;
+ int mv = n - index;
if (mv > 0)
- System.arraycopy(array, index + 1, array, index, mv);
- array[c] = null;
- count = c;
+ System.arraycopy(items, index + 1, items, index, mv);
+ items[n] = null;
+ count = n;
return true;
}
/**
* Internal version of removeAll for lists and sublists. In this
- * and other similar methods below, the span argument is, if
- * non-negative, the purported size of a list/sublist, or is left
- * negative if the size should be determined via count field under
- * lock.
+ * and other similar methods below, the bound argument is, if
+ * non-negative, the purported upper bound of a list/sublist, or
+ * is left negative if the bound should be determined via count
+ * field under lock.
*/
- final boolean internalRemoveAll(Collection> c, int origin, int span) {
- SequenceLock lock = this.lock;
+ final boolean internalRemoveAll(Collection> c, int origin, int bound) {
+ final SequenceLock lock = this.lock;
boolean removed = false;
lock.lock();
try {
- int fence = count;
- if (span >= 0 && origin + span < fence)
- fence = origin + span;
+ int n = count;
+ int fence = bound < 0 || bound > n ? n : bound;
if (origin >= 0 && origin < fence) {
for (Object x : c) {
- while (internalRemoveAt(internalIndexOf(x, array,
- origin, fence)))
+ while (rawRemoveAt(rawIndexOf(x, origin, fence)))
removed = true;
}
}
@@ -240,27 +292,30 @@ public class ReadMostlyVector impleme
return removed;
}
- final boolean internalRetainAll(Collection> c, int origin, int span) {
- SequenceLock lock = this.lock;
+ final boolean internalRetainAll(Collection> c, int origin, int bound) {
+ final SequenceLock lock = this.lock;
boolean removed = false;
if (c != this) {
lock.lock();
try {
+ Object[] items = array;
int i = origin;
- int fence = count;
- if (span >= 0 && origin + span < fence)
- fence = origin + span;
- while (i < fence) {
- if (c.contains(array[i]))
+ int n = count;
+ int fence = bound < 0 || bound > n ? n : bound;
+ while (i >= 0 && i < fence) {
+ if (c.contains(items[i]))
++i;
else {
--fence;
- int mv = --count - i;
+ int mv = --n - i;
if (mv > 0)
- System.arraycopy(array, i + 1, array, i, mv);
- removed = true;
+ System.arraycopy(items, i + 1, items, i, mv);
}
}
+ if (count != n) {
+ count = n;
+ removed = true;
+ }
} finally {
lock.unlock();
}
@@ -268,44 +323,45 @@ public class ReadMostlyVector impleme
return removed;
}
- final void internalClear(int origin, int span) {
- int c = count;
- int fence = c;
- if (span >= 0 && origin + span < fence)
- fence = origin + span;
+ final void internalClear(int origin, int bound) {
+ int n = count;
+ int fence = bound < 0 || bound > n ? n : bound;
if (origin >= 0 && origin < fence) {
+ Object[] items = array;
int removed = fence - origin;
- int newCount = c - removed;
- int mv = c - (origin + removed);
+ int newCount = n - removed;
+ int mv = n - (origin + removed);
if (mv > 0)
- System.arraycopy(array, origin + removed, array, origin, mv);
- for (int i = c; i < newCount; ++i)
- array[i] = null;
+ System.arraycopy(items, origin + removed, items, origin, mv);
+ for (int i = n; i < newCount; ++i)
+ items[i] = null;
count = newCount;
}
}
- final boolean internalContainsAll(Collection> coll, int origin, int span) {
- SequenceLock lock = this.lock;
+ final boolean internalContainsAll(Collection> c, int origin, int bound) {
+ final SequenceLock lock = this.lock;
boolean contained;
boolean locked = false;
try {
for (;;) {
long seq = lock.awaitAvailability();
+ int n = count;
Object[] items = array;
int len = items.length;
- int c = count;
- if (c > len)
+ if (n > len)
continue;
- int fence = c;
- if (span >= 0 && origin + span < fence)
- fence = origin + span;
- if (origin < 0 || fence > c)
+ int fence = bound < 0 || bound > n ? n : bound;
+ if (origin < 0)
contained = false;
else {
contained = true;
- for (Object e : coll) {
- if (internalIndexOf(e, items, origin, fence) < 0) {
+ for (Object e : c) {
+ int idx = (locked ?
+ rawIndexOf(e, origin, fence) :
+ validatedIndexOf(e, items, origin,
+ fence, seq));
+ if (idx < 0) {
contained = false;
break;
}
@@ -323,34 +379,28 @@ public class ReadMostlyVector impleme
return contained;
}
- final boolean internalEquals(List> list, int origin, int span) {
- SequenceLock lock = this.lock;
- boolean equal;
+ final boolean internalEquals(List> list, int origin, int bound) {
+ final SequenceLock lock = this.lock;
boolean locked = false;
+ boolean equal;
try {
for (;;) {
- equal = true;
long seq = lock.awaitAvailability();
Object[] items = array;
- int len = items.length;
- int c = count;
- if (c > len)
- continue;
- int fence = c;
- if (span >= 0 && origin + span < fence)
- fence = origin + span;
- if (origin < 0 || fence > c)
+ int n = count;
+ if (n > items.length || origin < 0)
equal = false;
else {
+ equal = true;
+ int fence = bound < 0 || bound > n ? n : bound;
Iterator> it = list.iterator();
for (int i = origin; i < fence; ++i) {
- if (!it.hasNext()) {
- equal = false;
- break;
- }
- Object x = it.next();
- Object y = items[i];
- if (x == null? y != null : (y == null || !x.equals(y))) {
+ Object x = items[i];
+ Object y;
+ if ((!locked && lock.getSequence() != seq) ||
+ !it.hasNext() ||
+ (y = it.next()) == null ?
+ x != null : !y.equals(x)) {
equal = false;
break;
}
@@ -370,8 +420,8 @@ public class ReadMostlyVector impleme
return equal;
}
- final int internalHashCode(int origin, int span) {
- SequenceLock lock = this.lock;
+ final int internalHashCode(int origin, int bound) {
+ final SequenceLock lock = this.lock;
int hash;
boolean locked = false;
try {
@@ -379,14 +429,12 @@ public class ReadMostlyVector impleme
hash = 1;
long seq = lock.awaitAvailability();
Object[] items = array;
+ int n = count;
int len = items.length;
- int c = count;
- if (c > len)
+ if (n > len)
continue;
- int fence = c;
- if (span >= 0 && origin + span < fence)
- fence = origin + span;
- if (origin >= 0 && fence <= c) {
+ int fence = bound < 0 || bound > n ? n : bound;
+ if (origin >= 0) {
for (int i = origin; i < fence; ++i) {
Object e = items[i];
hash = 31*hash + (e == null ? 0 : e.hashCode());
@@ -404,41 +452,42 @@ public class ReadMostlyVector impleme
return hash;
}
- final String internalToString(int origin, int span) {
- SequenceLock lock = this.lock;
+ final String internalToString(int origin, int bound) {
+ final SequenceLock lock = this.lock;
String ret;
boolean locked = false;
try {
- for (;;) {
+ outer:for (;;) {
long seq = lock.awaitAvailability();
Object[] items = array;
+ int n = count;
int len = items.length;
- int c = count;
- if (c > len)
+ if (n > len)
continue;
- int fence = c;
- if (span >= 0 && origin + span < fence)
- fence = origin + span;
- if (origin >= 0 && fence <= c) {
- if (origin == fence)
- ret = "[]";
- else {
- StringBuilder sb = new StringBuilder();
- sb.append('[');
- for (int i = origin;;) {
- Object e = items[i];
- sb.append(e == this ? "(this Collection)" : e);
- if (++i < fence)
- sb.append(',').append(' ');
- else {
- ret = sb.append(']').toString();
- break;
- }
+ int fence = bound < 0 || bound > n ? n : bound;
+ if (origin < 0 || origin == fence)
+ ret = "[]";
+ else {
+ StringBuilder sb = new StringBuilder();
+ sb.append('[');
+ for (int i = origin;;) {
+ Object e = items[i];
+ if (e == this)
+ sb.append("(this Collection)");
+ else if (!locked && lock.getSequence() != seq)
+ continue outer;
+ else
+ sb.append(e.toString());
+ if (++i < fence)
+ sb.append(',').append(' ');
+ else {
+ ret = sb.append(']').toString();
+ break;
}
}
- if (lock.getSequence() == seq)
- break;
}
+ if (lock.getSequence() == seq)
+ break;
lock.lock();
locked = true;
}
@@ -449,26 +498,25 @@ public class ReadMostlyVector impleme
return ret;
}
- final Object[] internalToArray(int origin, int span) {
+ final Object[] internalToArray(int origin, int bound) {
Object[] result;
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
boolean locked = false;
try {
for (;;) {
result = null;
long seq = lock.awaitAvailability();
Object[] items = array;
+ int n = count;
int len = items.length;
- int c = count;
- int fence = c;
- if (span >= 0 && origin + span < fence)
- fence = origin + span;
- if (c <= len && fence <= len) {
+ if (n > len)
+ continue;
+ int fence = bound < 0 || bound > n ? n : bound;
+ if (origin >= 0)
result = Arrays.copyOfRange(items, origin, fence,
Object[].class);
- if (lock.getSequence() == seq)
- break;
- }
+ if (lock.getSequence() == seq)
+ break;
lock.lock();
locked = true;
}
@@ -479,33 +527,36 @@ public class ReadMostlyVector impleme
return result;
}
- final T[] internalToArray(T[] a, int origin, int span) {
+ @SuppressWarnings("unchecked")
+ final T[] internalToArray(T[] a, int origin, int bound) {
+ int alen = a.length;
T[] result;
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
boolean locked = false;
try {
for (;;) {
long seq = lock.awaitAvailability();
Object[] items = array;
+ int n = count;
int len = items.length;
- int c = count;
- int fence = c;
- if (span >= 0 && origin + span < fence)
- fence = origin + span;
- if (c <= len && fence <= len) {
- if (a.length < count)
- result = (T[]) Arrays.copyOfRange(array, origin,
- fence, a.getClass());
- else {
- int n = fence - origin;
- System.arraycopy(array, 0, a, origin, fence - origin);
- if (a.length > n)
- a[n] = null;
- result = a;
- }
- if (lock.getSequence() == seq)
- break;
+ if (n > len)
+ continue;
+ int fence = bound < 0 || bound > n ? n : bound;
+ int rlen = fence - origin;
+ if (rlen < 0)
+ rlen = 0;
+ if (origin < 0 || alen >= rlen) {
+ if (rlen > 0)
+ System.arraycopy(items, 0, a, origin, rlen);
+ if (alen > rlen)
+ a[rlen] = null;
+ result = a;
}
+ else
+ result = (T[]) Arrays.copyOfRange(items, origin,
+ fence, a.getClass());
+ if (lock.getSequence() == seq)
+ break;
lock.lock();
locked = true;
}
@@ -519,10 +570,10 @@ public class ReadMostlyVector impleme
// public List methods
public boolean add(E e) {
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
lock.lock();
try {
- internalAdd(e);
+ rawAdd(e);
} finally {
lock.unlock();
}
@@ -530,10 +581,10 @@ public class ReadMostlyVector impleme
}
public void add(int index, E element) {
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
lock.lock();
try {
- internalAddAt(index, element);
+ rawAddAt(index, element);
} finally {
lock.unlock();
}
@@ -544,13 +595,15 @@ public class ReadMostlyVector impleme
int len = elements.length;
if (len == 0)
return false;
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
lock.lock();
try {
- int newCount = count + len;
- if (newCount >= array.length)
- grow(newCount);
- System.arraycopy(elements, 0, array, count, len);
+ Object[] items = array;
+ int n = count;
+ int newCount = n + len;
+ if (newCount >= items.length)
+ items = grow(newCount);
+ System.arraycopy(elements, 0, items, n, len);
count = newCount;
} finally {
lock.unlock();
@@ -559,12 +612,12 @@ public class ReadMostlyVector impleme
}
public boolean addAll(int index, Collection extends E> c) {
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
boolean ret;
Object[] elements = c.toArray();
lock.lock();
try {
- ret = internalAddAllAt(index, elements);
+ ret = rawAddAllAt(index, elements);
} finally {
lock.unlock();
}
@@ -572,11 +625,13 @@ public class ReadMostlyVector impleme
}
public void clear() {
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
lock.lock();
try {
- for (int i = 0; i < count; i++)
- array[i] = null;
+ int n = count;
+ Object[] items = array;
+ for (int i = 0; i < n; i++)
+ items[i] = null;
count = 0;
} finally {
lock.unlock();
@@ -596,32 +651,21 @@ public class ReadMostlyVector impleme
return true;
if (!(o instanceof List))
return false;
- return internalEquals((List>)(o), 0, -1);
+ return internalEquals((List>)o, 0, -1);
}
public E get(int index) {
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
for (;;) {
long seq = lock.awaitAvailability();
+ int n = count;
Object[] items = array;
- int len = items.length;
- int c = count;
- if (c > len)
- continue;
- E e; boolean ex;
- if (index < 0 || index >= c) {
- e = null;
- ex = true;
- }
- else {
- e = (E)items[index];
- ex = false;
- }
+ @SuppressWarnings("unchecked")
+ E e = (index < items.length) ? (E) items[index] : null;
if (lock.getSequence() == seq) {
- if (ex)
+ if (index >= n)
throw new ArrayIndexOutOfBoundsException(index);
- else
- return e;
+ return e;
}
}
}
@@ -631,83 +675,73 @@ public class ReadMostlyVector impleme
}
public int indexOf(Object o) {
- SequenceLock lock = this.lock;
- long seq = lock.awaitAvailability();
- Object[] items = array;
- int c = count;
- if (c <= items.length) {
- int idx = internalIndexOf(o, items, 0, c);
- if (lock.getSequence() == seq)
- return idx;
- }
- lock.lock();
- try {
- return internalIndexOf(o, array, 0, count);
- } finally {
- lock.unlock();
- }
+ return indexOf(o, 0);
}
public boolean isEmpty() {
- long ignore = lock.getSequence();
return count == 0;
}
public Iterator iterator() {
- return new Itr(this, 0);
+ return new Itr(this, 0);
}
public int lastIndexOf(Object o) {
- SequenceLock lock = this.lock;
- long seq = lock.awaitAvailability();
- Object[] items = array;
- int c = count;
- if (c <= items.length) {
- int idx = internalLastIndexOf(o, items, c - 1, 0);
- if (lock.getSequence() == seq)
- return idx;
- }
- lock.lock();
- try {
- return internalLastIndexOf(o, array, count-1, 0);
- } finally {
- lock.unlock();
+ final SequenceLock lock = this.lock;
+ for (;;) {
+ long seq = lock.awaitAvailability();
+ Object[] items = array;
+ int n = count;
+ if (n <= items.length) {
+ for (int i = n - 1; i >= 0; --i) {
+ Object e = items[i];
+ if (lock.getSequence() != seq) {
+ lock.lock();
+ try {
+ return rawLastIndexOf(o, count - 1, 0);
+ } finally {
+ lock.unlock();
+ }
+ }
+ else if ((o == null) ? e == null : o.equals(e))
+ return i;
+ }
+ return -1;
+ }
}
}
public ListIterator listIterator() {
- return new Itr(this, 0);
+ return new Itr(this, 0);
}
public ListIterator listIterator(int index) {
- return new Itr(this, index);
+ return new Itr(this, index);
}
public E remove(int index) {
- SequenceLock lock = this.lock;
- E oldValue;
+ final SequenceLock lock = this.lock;
lock.lock();
try {
if (index < 0 || index >= count)
throw new ArrayIndexOutOfBoundsException(index);
- oldValue = (E)array[index];
- internalRemoveAt(index);
+ @SuppressWarnings("unchecked")
+ E oldValue = (E) array[index];
+ rawRemoveAt(index);
+ return oldValue;
} finally {
lock.unlock();
}
- return oldValue;
}
public boolean remove(Object o) {
- SequenceLock lock = this.lock;
- boolean removed;
+ final SequenceLock lock = this.lock;
lock.lock();
try {
- removed = internalRemoveAt(internalIndexOf(o, array, 0, count));
+ return rawRemoveAt(rawIndexOf(o, 0, count));
} finally {
lock.unlock();
}
- return removed;
}
public boolean removeAll(Collection> c) {
@@ -719,22 +753,22 @@ public class ReadMostlyVector impleme
}
public E set(int index, E element) {
- E oldValue;
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
lock.lock();
try {
+ Object[] items = array;
if (index < 0 || index >= count)
throw new ArrayIndexOutOfBoundsException(index);
- oldValue = (E)array[index];
- array[index] = element;
+ @SuppressWarnings("unchecked")
+ E oldValue = (E) items[index];
+ items[index] = element;
+ return oldValue;
} finally {
lock.unlock();
}
- return oldValue;
}
public int size() {
- long ignore = lock.getSequence();
return count;
}
@@ -743,7 +777,7 @@ public class ReadMostlyVector impleme
int ssize = toIndex - fromIndex;
if (fromIndex < 0 || toIndex > c || ssize < 0)
throw new IndexOutOfBoundsException();
- return new ReadMostlyVectorSublist(this, fromIndex, ssize);
+ return new ReadMostlyVectorSublist(this, fromIndex, ssize);
}
public Object[] toArray() {
@@ -761,26 +795,24 @@ public class ReadMostlyVector impleme
// 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 true if the element was added
+ * @return {@code true} if the element was added
*/
public boolean addIfAbsent(E e) {
- boolean added;
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
lock.lock();
try {
- if (internalIndexOf(e, array, 0, count) < 0) {
- internalAdd(e);
- added = true;
+ if (rawIndexOf(e, 0, count) < 0) {
+ rawAdd(e);
+ return true;
}
else
- added = false;
+ return false;
} finally {
lock.unlock();
}
- return added;
}
/**
@@ -802,9 +834,10 @@ public class ReadMostlyVector impleme
lock.lock();
try {
for (int i = 0; i < clen; ++i) {
- Object e = cs[i];
- if (internalIndexOf(e, array, 0, count) < 0) {
- internalAdd((E)e);
+ @SuppressWarnings("unchecked")
+ E e = (E) cs[i];
+ if (rawIndexOf(e, 0, count) < 0) {
+ rawAdd(e);
++added;
}
}
@@ -815,123 +848,110 @@ public class ReadMostlyVector impleme
return added;
}
+ /**
+ * Returns an iterator operating over a snapshot copy of the
+ * elements of this collection created upon construction of the
+ * iterator. The iterator does NOT support the
+ * {@code remove} method.
+ *
+ * @return an iterator over the elements in this list in proper sequence
+ */
+ public Iterator snapshotIterator() {
+ return new SnapshotIterator(this);
+ }
+
+ static final class SnapshotIterator implements Iterator {
+ private final Object[] items;
+ private int cursor;
+ SnapshotIterator(ReadMostlyVector v) { items = v.toArray(); }
+ public boolean hasNext() { return cursor < items.length; }
+ @SuppressWarnings("unchecked")
+ public E next() {
+ if (cursor < items.length)
+ return (E) items[cursor++];
+ throw new NoSuchElementException();
+ }
+ public void remove() { throw new UnsupportedOperationException() ; }
+ }
+
// Vector-only methods
/** See {@link Vector#firstElement} */
public E firstElement() {
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
for (;;) {
long seq = lock.awaitAvailability();
Object[] items = array;
- int len = items.length;
- int c = count;
- if (c > len || c < 0)
- continue;
- E e; boolean ex;
- if (c == 0) {
- e = null;
- ex = true;
- }
- else {
- e = (E)items[0];
- ex = false;
- }
+ int n = count;
+ @SuppressWarnings("unchecked")
+ E e = (items.length > 0) ? (E) items[0] : null;
if (lock.getSequence() == seq) {
- if (ex)
+ if (n <= 0)
throw new NoSuchElementException();
- else
- return e;
+ return e;
}
}
}
/** See {@link Vector#lastElement} */
public E lastElement() {
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
for (;;) {
long seq = lock.awaitAvailability();
Object[] items = array;
- int len = items.length;
- int c = count;
- if (c > len || c < 0)
- continue;
- E e; boolean ex;
- if (c == 0) {
- e = null;
- ex = true;
- }
- else {
- e = (E)items[c - 1];
- ex = false;
- }
+ int n = count;
+ @SuppressWarnings("unchecked")
+ E e = (n > 0 && items.length >= n) ? (E) items[n - 1] : null;
if (lock.getSequence() == seq) {
- if (ex)
+ if (n <= 0)
throw new NoSuchElementException();
- else
- return e;
+ return e;
}
}
}
/** See {@link Vector#indexOf(Object, int)} */
public int indexOf(Object o, int index) {
- SequenceLock lock = this.lock;
- int idx = 0;
- boolean ex = false;
+ final SequenceLock lock = this.lock;
long seq = lock.awaitAvailability();
Object[] items = array;
- int c = count;
- boolean retry = false;
- if (c > items.length)
- retry = true;
- else if (index < 0)
- ex = true;
- else
- idx = internalIndexOf(o, items, index, c);
- if (retry || lock.getSequence() != seq) {
+ int n = count;
+ int idx = -1;
+ if (n <= items.length)
+ idx = validatedIndexOf(o, items, index, n, seq);
+ if (lock.getSequence() != seq) {
lock.lock();
try {
- if (index < 0)
- ex = true;
- else
- idx = internalIndexOf(o, array, 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) {
- SequenceLock lock = this.lock;
- int idx = 0;
- boolean ex = false;
+ final SequenceLock lock = this.lock;
long seq = lock.awaitAvailability();
Object[] items = array;
- int c = count;
- boolean retry = false;
- if (c > items.length)
- retry = true;
- else if (index >= c)
- ex = true;
- else
- idx = internalLastIndexOf(o, items, index, 0);
- if (retry || lock.getSequence() != seq) {
+ int n = count;
+ int idx = -1;
+ if (index < Math.min(n, items.length))
+ idx = validatedLastIndexOf(o, items, index, 0, seq);
+ if (lock.getSequence() != seq) {
lock.lock();
try {
- if (index >= count)
- ex = true;
- else
- idx = internalLastIndexOf(o, array, index, 0);
+ 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;
}
@@ -939,15 +959,16 @@ public class ReadMostlyVector impleme
public void setSize(int newSize) {
if (newSize < 0)
throw new ArrayIndexOutOfBoundsException(newSize);
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
lock.lock();
try {
- int c = count;
- if (newSize > c)
+ int n = count;
+ if (newSize > n)
grow(newSize);
else {
- for (int i = newSize ; i < c ; i++)
- array[i] = null;
+ Object[] items = array;
+ for (int i = newSize ; i < n ; i++)
+ items[i] = null;
}
count = newSize;
} finally {
@@ -957,7 +978,7 @@ public class ReadMostlyVector impleme
/** See {@link Vector#copyInto} */
public void copyInto(Object[] anArray) {
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
lock.lock();
try {
System.arraycopy(array, 0, anArray, 0, count);
@@ -968,11 +989,13 @@ public class ReadMostlyVector impleme
/** See {@link Vector#trimToSize} */
public void trimToSize() {
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
lock.lock();
try {
- if (count < array.length)
- array = Arrays.copyOf(array, count);
+ Object[] items = array;
+ int n = count;
+ if (n < items.length)
+ array = Arrays.copyOf(items, n);
} finally {
lock.unlock();
}
@@ -981,7 +1004,7 @@ public class ReadMostlyVector impleme
/** See {@link Vector#ensureCapacity} */
public void ensureCapacity(int minCapacity) {
if (minCapacity > 0) {
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
lock.lock();
try {
if (minCapacity - array.length > 0)
@@ -994,12 +1017,11 @@ public class ReadMostlyVector impleme
/** See {@link Vector#elements} */
public Enumeration elements() {
- return new Itr(this, 0);
+ return new Itr(this, 0);
}
/** See {@link Vector#capacity} */
public int capacity() {
- long ignore = lock.getSequence();
return array.length;
}
@@ -1040,33 +1062,32 @@ public class ReadMostlyVector impleme
// other methods
- public Object clone() {
- SequenceLock lock = this.lock;
+ public ReadMostlyVector clone() {
+ final SequenceLock lock = this.lock;
Object[] a = null;
- int c;
boolean retry = false;
long seq = lock.awaitAvailability();
Object[] items = array;
- c = count;
- if (c <= items.length)
- a = Arrays.copyOf(items, c);
+ int n = count;
+ if (n <= items.length)
+ a = Arrays.copyOf(items, n);
else
retry = true;
if (retry || lock.getSequence() != seq) {
lock.lock();
try {
- c = count;
- a = Arrays.copyOf(array, c);
+ n = count;
+ a = Arrays.copyOf(array, n);
} finally {
lock.unlock();
}
}
- return new ReadMostlyVector(a, c, capacityIncrement);
+ return new ReadMostlyVector(a, n, capacityIncrement);
}
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
- SequenceLock lock = this.lock;
+ final SequenceLock lock = this.lock;
lock.lock();
try {
s.defaultWriteObject();
@@ -1075,16 +1096,16 @@ public class ReadMostlyVector impleme
}
}
- static final class Itr implements ListIterator, Enumeration {
+ static final class Itr implements ListIterator, Enumeration {
final ReadMostlyVector list;
final SequenceLock lock;
Object[] items;
- Object next, prev;
+ E next, prev;
long seq;
int cursor;
int fence;
int lastRet;
- boolean haveNext, havePrev;
+ boolean validNext, validPrev;
Itr(ReadMostlyVector list, int index) {
this.list = list;
@@ -1097,51 +1118,68 @@ public class ReadMostlyVector impleme
}
private void refresh() {
+ validNext = validPrev = false;
do {
seq = lock.awaitAvailability();
items = list.array;
- fence = list.count;
- } while (lock.getSequence() != seq);
+ } while ((fence = list.count) > items.length ||
+ lock.getSequence() != seq);
}
+ @SuppressWarnings("unchecked")
public boolean hasNext() {
+ boolean valid;
int i = cursor;
- while (i < fence && i >= 0) {
+ for (;;) {
+ if (i >= fence || i < 0 || i >= items.length) {
+ valid = false;
+ break;
+ }
+ next = (E) items[i];
if (lock.getSequence() == seq) {
- next = items[i];
- return haveNext = true;
+ valid = true;
+ break;
}
refresh();
}
- return false;
+ return validNext = valid;
}
+ @SuppressWarnings("unchecked")
public boolean hasPrevious() {
- int i = cursor;
- while (i <= fence && i > 0) {
+ boolean valid;
+ int i = cursor - 1;
+ for (;;) {
+ if (i >= fence || i < 0 || i >= items.length) {
+ valid = false;
+ break;
+ }
+ prev = (E) items[i];
if (lock.getSequence() == seq) {
- prev = items[i - 1];
- return havePrev = true;
+ valid = true;
+ break;
}
refresh();
}
- return false;
+ return validPrev = valid;
}
public E next() {
- if (!haveNext && !hasNext())
- throw new NoSuchElementException();
- haveNext = false;
- lastRet = cursor++;
- return (E) next;
+ if (validNext || hasNext()) {
+ validNext = validPrev = false;
+ lastRet = cursor++;
+ return next;
+ }
+ throw new NoSuchElementException();
}
public E previous() {
- if (!havePrev && !hasPrevious())
- throw new NoSuchElementException();
- havePrev = false;
- lastRet = cursor--;
- return (E) prev;
+ if (validPrev || hasPrevious()) {
+ validNext = validPrev = false;
+ lastRet = cursor--;
+ return prev;
+ }
+ throw new NoSuchElementException();
}
public void remove() {
@@ -1196,12 +1234,16 @@ public class ReadMostlyVector impleme
public int previousIndex() { return cursor - 1; }
}
- static final class ReadMostlyVectorSublist implements List, RandomAccess, java.io.Serializable {
+ static final class ReadMostlyVectorSublist
+ implements List, RandomAccess, java.io.Serializable {
+ static final long serialVersionUID = 3041673470172026059L;
+
final ReadMostlyVector list;
final int offset;
volatile int size;
- ReadMostlyVectorSublist(ReadMostlyVector list, int offset, int size) {
+ ReadMostlyVectorSublist(ReadMostlyVector list,
+ int offset, int size) {
this.list = list;
this.offset = offset;
this.size = size;
@@ -1213,11 +1255,11 @@ public class ReadMostlyVector impleme
}
public boolean add(E element) {
- SequenceLock lock = list.lock;
+ final SequenceLock lock = list.lock;
lock.lock();
try {
int c = size;
- list.internalAddAt(c + offset, element);
+ list.rawAddAt(c + offset, element);
size = c + 1;
} finally {
lock.unlock();
@@ -1226,12 +1268,12 @@ public class ReadMostlyVector impleme
}
public void add(int index, E element) {
- SequenceLock lock = list.lock;
+ final SequenceLock lock = list.lock;
lock.lock();
try {
if (index < 0 || index > size)
throw new ArrayIndexOutOfBoundsException(index);
- list.internalAddAt(index + offset, element);
+ list.rawAddAt(index + offset, element);
++size;
} finally {
lock.unlock();
@@ -1240,45 +1282,43 @@ public class ReadMostlyVector impleme
public boolean addAll(Collection extends E> c) {
Object[] elements = c.toArray();
- int added;
- SequenceLock lock = list.lock;
+ final SequenceLock lock = list.lock;
lock.lock();
try {
int s = size;
int pc = list.count;
- list.internalAddAllAt(offset + s, elements);
- added = list.count - pc;
+ list.rawAddAllAt(offset + s, elements);
+ int added = list.count - pc;
size = s + added;
+ return added != 0;
} finally {
lock.unlock();
}
- return added != 0;
}
public boolean addAll(int index, Collection extends E> c) {
Object[] elements = c.toArray();
- int added;
- SequenceLock lock = list.lock;
+ final SequenceLock lock = list.lock;
lock.lock();
try {
int s = size;
if (index < 0 || index > s)
throw new ArrayIndexOutOfBoundsException(index);
int pc = list.count;
- list.internalAddAllAt(index + offset, elements);
- added = list.count - pc;
+ list.rawAddAllAt(index + offset, elements);
+ int added = list.count - pc;
size = s + added;
+ return added != 0;
} finally {
lock.unlock();
}
- return added != 0;
}
public void clear() {
- SequenceLock lock = list.lock;
+ final SequenceLock lock = list.lock;
lock.lock();
try {
- list.internalClear(offset, size);
+ list.internalClear(offset, offset + size);
size = 0;
} finally {
lock.unlock();
@@ -1290,7 +1330,7 @@ public class ReadMostlyVector impleme
}
public boolean containsAll(Collection> c) {
- return list.internalContainsAll(c, offset, size);
+ return list.internalContainsAll(c, offset, offset + size);
}
public boolean equals(Object o) {
@@ -1298,7 +1338,7 @@ public class ReadMostlyVector impleme
return true;
if (!(o instanceof List))
return false;
- return list.internalEquals((List>)(o), offset, size);
+ return list.internalEquals((List>)(o), offset, offset + size);
}
public E get(int index) {
@@ -1308,22 +1348,23 @@ public class ReadMostlyVector impleme
}
public int hashCode() {
- return list.internalHashCode(offset, size);
+ return list.internalHashCode(offset, offset + size);
}
public int indexOf(Object o) {
- SequenceLock lock = list.lock;
+ final SequenceLock lock = list.lock;
long seq = lock.awaitAvailability();
Object[] items = list.array;
int c = list.count;
if (c <= items.length) {
- int idx = internalIndexOf(o, items, offset, offset+size);
+ int idx = list.validatedIndexOf(o, items, offset,
+ offset + size, seq);
if (lock.getSequence() == seq)
return idx < 0 ? -1 : idx - offset;
}
lock.lock();
try {
- int idx = internalIndexOf(o, list.array, offset, offset+size);
+ int idx = list.rawIndexOf(o, offset, offset + size);
return idx < 0 ? -1 : idx - offset;
} finally {
lock.unlock();
@@ -1335,23 +1376,23 @@ public class ReadMostlyVector impleme
}
public Iterator iterator() {
- return new SubItr(this, offset);
+ return new SubItr(this, offset);
}
public int lastIndexOf(Object o) {
- SequenceLock lock = list.lock;
+ final SequenceLock lock = list.lock;
long seq = lock.awaitAvailability();
Object[] items = list.array;
int c = list.count;
if (c <= items.length) {
- int idx = internalLastIndexOf(o, items, offset+size-1, offset);
+ int idx = list.validatedLastIndexOf(o, items, offset+size-1,
+ offset, seq);
if (lock.getSequence() == seq)
return idx < 0 ? -1 : idx - offset;
}
lock.lock();
try {
- int idx = internalLastIndexOf(o, list.array, offset+size-1,
- offset);
+ int idx = list.rawLastIndexOf(o, offset + size - 1, offset);
return idx < 0 ? -1 : idx - offset;
} finally {
lock.unlock();
@@ -1359,52 +1400,53 @@ public class ReadMostlyVector impleme
}
public ListIterator listIterator() {
- return new SubItr(this, offset);
+ return new SubItr(this, offset);
}
public ListIterator listIterator(int index) {
- return new SubItr(this, index + offset);
+ return new SubItr(this, index + offset);
}
public E remove(int index) {
- E result;
- SequenceLock lock = list.lock;
+ final SequenceLock lock = list.lock;
lock.lock();
try {
- if (index < 0 || index >= size)
- throw new ArrayIndexOutOfBoundsException(index);
+ Object[] items = list.array;
int i = index + offset;
- result = (E)list.array[i];
- list.internalRemoveAt(i);
+ if (index < 0 || index >= size || i >= items.length)
+ throw new ArrayIndexOutOfBoundsException(index);
+ @SuppressWarnings("unchecked")
+ E result = (E) items[i];
+ list.rawRemoveAt(i);
size--;
+ return result;
} finally {
lock.unlock();
}
- return result;
}
public boolean remove(Object o) {
- boolean removed = false;
- SequenceLock lock = list.lock;
+ final SequenceLock lock = list.lock;
lock.lock();
try {
- if (list.internalRemoveAt(internalIndexOf(o, list.array, offset,
- offset+size))) {
- removed = true;
+ if (list.rawRemoveAt(list.rawIndexOf(o, offset,
+ offset + size))) {
--size;
+ return true;
}
+ else
+ return false;
} finally {
lock.unlock();
}
- return removed;
}
public boolean removeAll(Collection> c) {
- return list.internalRemoveAll(c, offset, size);
+ return list.internalRemoveAll(c, offset, offset + size);
}
public boolean retainAll(Collection> c) {
- return list.internalRetainAll(c, offset, size);
+ return list.internalRetainAll(c, offset, offset + size);
}
public E set(int index, E element) {
@@ -1422,19 +1464,19 @@ public class ReadMostlyVector impleme
int ssize = toIndex - fromIndex;
if (fromIndex < 0 || toIndex > c || ssize < 0)
throw new IndexOutOfBoundsException();
- return new ReadMostlyVectorSublist(list, offset+fromIndex, ssize);
+ return new ReadMostlyVectorSublist(list, offset+fromIndex, ssize);
}
public Object[] toArray() {
- return list.internalToArray(offset, size);
+ return list.internalToArray(offset, offset + size);
}
public T[] toArray(T[] a) {
- return list.internalToArray(a, offset, size);
+ return list.internalToArray(a, offset, offset + size);
}
public String toString() {
- return list.internalToString(offset, size);
+ return list.internalToString(offset, offset + size);
}
}
@@ -1444,12 +1486,12 @@ public class ReadMostlyVector impleme
final ReadMostlyVector list;
final SequenceLock lock;
Object[] items;
- Object next, prev;
+ E next, prev;
long seq;
int cursor;
int fence;
int lastRet;
- boolean haveNext, havePrev;
+ boolean validNext, validPrev;
SubItr(ReadMostlyVectorSublist sublist, int index) {
this.sublist = sublist;
@@ -1463,53 +1505,72 @@ public class ReadMostlyVector impleme
}
private void refresh() {
+ validNext = validPrev = false;
do {
+ int n;
seq = lock.awaitAvailability();
items = list.array;
- int c = list.count;
+ if ((n = list.count) > items.length)
+ continue;
int b = sublist.offset + sublist.size;
- fence = b < c ? b : c;
+ fence = b < n ? b : n;
} while (lock.getSequence() != seq);
}
+ @SuppressWarnings("unchecked")
public boolean hasNext() {
+ boolean valid;
int i = cursor;
- while (i < fence && i >= 0) {
+ for (;;) {
+ if (i >= fence || i < 0 || i >= items.length) {
+ valid = false;
+ break;
+ }
+ next = (E) items[i];
if (lock.getSequence() == seq) {
- next = items[i];
- return haveNext = true;
+ valid = true;
+ break;
}
refresh();
}
- return false;
+ return validNext = valid;
}
+ @SuppressWarnings("unchecked")
public boolean hasPrevious() {
- int i = cursor;
- while (i <= fence && i > 0) {
+ boolean valid;
+ int i = cursor - 1;
+ for (;;) {
+ if (i >= fence || i < 0 || i >= items.length) {
+ valid = false;
+ break;
+ }
+ prev = (E) items[i];
if (lock.getSequence() == seq) {
- prev = items[i - 1];
- return havePrev = true;
+ valid = true;
+ break;
}
refresh();
}
- return false;
+ return validPrev = valid;
}
public E next() {
- if (!haveNext && !hasNext())
- throw new NoSuchElementException();
- haveNext = false;
- lastRet = cursor++;
- return (E) next;
+ if (validNext || hasNext()) {
+ validNext = validPrev = false;
+ lastRet = cursor++;
+ return next;
+ }
+ throw new NoSuchElementException();
}
public E previous() {
- if (!havePrev && !hasPrevious())
- throw new NoSuchElementException();
- havePrev = false;
- lastRet = cursor--;
- return (E) prev;
+ if (validPrev || hasPrevious()) {
+ validNext = validPrev = false;
+ lastRet = cursor--;
+ return prev;
+ }
+ throw new NoSuchElementException();
}
public int nextIndex() {
@@ -1572,4 +1633,3 @@ public class ReadMostlyVector impleme
}
}
-