summaryrefslogtreecommitdiffstats
path: root/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
diff options
context:
space:
mode:
Diffstat (limited to 'luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java')
-rw-r--r--luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java161
1 files changed, 70 insertions, 91 deletions
diff --git a/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java b/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
index 3cfe6d5..9dca1b3 100644
--- a/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
@@ -5,13 +5,15 @@
*/
package java.util.concurrent;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
+
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
import java.util.AbstractQueue;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
-import java.lang.ref.WeakReference;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
// BEGIN android-note
// removed link to collections framework docs
@@ -46,7 +48,7 @@ import java.lang.ref.WeakReference;
*
* @since 1.5
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
*/
public class ArrayBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
@@ -95,14 +97,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
// Internal helper methods
/**
- * Circularly increment i.
- */
- final int inc(int i) {
- return (++i == items.length) ? 0 : i;
- }
-
- /**
- * Circularly decrement i.
+ * Circularly decrements array index i.
*/
final int dec(int i) {
return ((i == 0) ? items.length : i) - 1;
@@ -117,24 +112,15 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
}
/**
- * Throws NullPointerException if argument is null.
- *
- * @param v the element
- */
- private static void checkNotNull(Object v) {
- if (v == null)
- throw new NullPointerException();
- }
-
- /**
* Inserts element at current put position, advances, and signals.
* Call only when holding lock.
*/
private void enqueue(E x) {
// assert lock.getHoldCount() == 1;
// assert items[putIndex] == null;
+ final Object[] items = this.items;
items[putIndex] = x;
- putIndex = inc(putIndex);
+ if (++putIndex == items.length) putIndex = 0;
count++;
notEmpty.signal();
}
@@ -150,7 +136,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex];
items[takeIndex] = null;
- takeIndex = inc(takeIndex);
+ if (++takeIndex == items.length) takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
@@ -171,7 +157,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
if (removeIndex == takeIndex) {
// removing front item; just advance
items[takeIndex] = null;
- takeIndex = inc(takeIndex);
+ if (++takeIndex == items.length) takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
@@ -179,17 +165,15 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
// an "interior" remove
// slide over all others up through putIndex.
- final int putIndex = this.putIndex;
- for (int i = removeIndex;;) {
- int next = inc(i);
- if (next != putIndex) {
- items[i] = items[next];
- i = next;
- } else {
- items[i] = null;
- this.putIndex = i;
+ for (int i = removeIndex, putIndex = this.putIndex;;) {
+ int pred = i;
+ if (++i == items.length) i = 0;
+ if (i == putIndex) {
+ items[pred] = null;
+ this.putIndex = pred;
break;
}
+ items[pred] = items[i];
}
count--;
if (itrs != null)
@@ -254,7 +238,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
int i = 0;
try {
for (E e : c) {
- checkNotNull(e);
+ if (e == null) throw new NullPointerException();
items[i++] = e;
}
} catch (ArrayIndexOutOfBoundsException ex) {
@@ -292,7 +276,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
- checkNotNull(e);
+ if (e == null) throw new NullPointerException();
final ReentrantLock lock = this.lock;
lock.lock();
try {
@@ -315,7 +299,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
* @throws NullPointerException {@inheritDoc}
*/
public void put(E e) throws InterruptedException {
- checkNotNull(e);
+ if (e == null) throw new NullPointerException();
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
@@ -338,7 +322,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
public boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException {
- checkNotNull(e);
+ if (e == null) throw new NullPointerException();
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
@@ -462,11 +446,11 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
*/
public boolean remove(Object o) {
if (o == null) return false;
- final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count > 0) {
+ final Object[] items = this.items;
final int putIndex = this.putIndex;
int i = takeIndex;
do {
@@ -474,7 +458,8 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
removeAt(i);
return true;
}
- } while ((i = inc(i)) != putIndex);
+ if (++i == items.length) i = 0;
+ } while (i != putIndex);
}
return false;
} finally {
@@ -492,17 +477,18 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
*/
public boolean contains(Object o) {
if (o == null) return false;
- final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count > 0) {
+ final Object[] items = this.items;
final int putIndex = this.putIndex;
int i = takeIndex;
do {
if (o.equals(items[i]))
return true;
- } while ((i = inc(i)) != putIndex);
+ if (++i == items.length) i = 0;
+ } while (i != putIndex);
}
return false;
} finally {
@@ -524,19 +510,14 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
* @return an array containing all of the elements in this queue
*/
public Object[] toArray() {
- final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
- final int count = this.count;
- Object[] a = new Object[count];
- int n = items.length - takeIndex;
- if (count <= n) {
- System.arraycopy(items, takeIndex, a, 0, count);
- } else {
- System.arraycopy(items, takeIndex, a, 0, n);
- System.arraycopy(items, 0, a, n, count - n);
- }
+ final Object[] items = this.items;
+ final int end = takeIndex + count;
+ final Object[] a = Arrays.copyOfRange(items, takeIndex, end);
+ if (end != putIndex)
+ System.arraycopy(items, 0, a, items.length - takeIndex, putIndex);
return a;
} finally {
lock.unlock();
@@ -564,7 +545,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
* The following code can be used to dump the queue into a newly
* allocated array of {@code String}:
*
- * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+ * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
@@ -580,24 +561,22 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
- final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
+ final Object[] items = this.items;
final int count = this.count;
- final int len = a.length;
- if (len < count)
- a = (T[])java.lang.reflect.Array.newInstance(
- a.getClass().getComponentType(), count);
- int n = items.length - takeIndex;
- if (count <= n)
- System.arraycopy(items, takeIndex, a, 0, count);
- else {
- System.arraycopy(items, takeIndex, a, 0, n);
- System.arraycopy(items, 0, a, n, count - n);
+ final int firstLeg = Math.min(items.length - takeIndex, count);
+ if (a.length < count) {
+ a = (T[]) Arrays.copyOfRange(items, takeIndex, takeIndex + count,
+ a.getClass());
+ } else {
+ System.arraycopy(items, takeIndex, a, 0, firstLeg);
+ if (a.length > count)
+ a[count] = null;
}
- if (len > count)
- a[count] = null;
+ if (firstLeg < count)
+ System.arraycopy(items, 0, a, firstLeg, putIndex);
return a;
} finally {
lock.unlock();
@@ -612,14 +591,16 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
if (k == 0)
return "[]";
+ final Object[] items = this.items;
StringBuilder sb = new StringBuilder();
sb.append('[');
- for (int i = takeIndex; ; i = inc(i)) {
+ for (int i = takeIndex; ; ) {
Object e = items[i];
sb.append(e == this ? "(this Collection)" : e);
if (--k == 0)
return sb.append(']').toString();
sb.append(',').append(' ');
+ if (++i == items.length) i = 0;
}
} finally {
lock.unlock();
@@ -641,7 +622,8 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
int i = takeIndex;
do {
items[i] = null;
- } while ((i = inc(i)) != putIndex);
+ if (++i == items.length) i = 0;
+ } while (i != putIndex);
takeIndex = putIndex;
count = 0;
if (itrs != null)
@@ -671,7 +653,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c, int maxElements) {
- checkNotNull(c);
+ if (c == null) throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
if (maxElements <= 0)
@@ -689,7 +671,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
E x = (E) items[take];
c.add(x);
items[take] = null;
- take = inc(take);
+ if (++take == items.length) take = 0;
i++;
}
return n;
@@ -717,12 +699,8 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
* Returns an iterator over the elements in this queue in proper sequence.
* The elements will be returned in order from first (head) to last (tail).
*
- * <p>The returned iterator is a "weakly consistent" iterator that
- * will never throw {@link java.util.ConcurrentModificationException
- * ConcurrentModificationException}, and guarantees to traverse
- * elements as they existed upon construction of the iterator, and
- * may (but is not guaranteed to) reflect any modifications
- * subsequent to construction.
+ * <p>The returned iterator is
+ * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
*
* @return an iterator over the elements in this queue in proper sequence
*/
@@ -796,13 +774,13 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
}
/** Incremented whenever takeIndex wraps around to 0 */
- int cycles = 0;
+ int cycles;
/** Linked list of weak iterator references */
private Node head;
/** Used to expunge stale iterators */
- private Node sweeper = null;
+ private Node sweeper;
private static final int SHORT_SWEEP_PROBES = 4;
private static final int LONG_SWEEP_PROBES = 16;
@@ -910,7 +888,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
}
/**
- * Called whenever an interior remove (not at takeIndex) occured.
+ * Called whenever an interior remove (not at takeIndex) occurred.
*
* Notifies all iterators, and expunges any that are now stale.
*/
@@ -1059,9 +1037,8 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
private int incCursor(int index) {
// assert lock.getHoldCount() == 1;
- index = inc(index);
- if (index == putIndex)
- index = NONE;
+ if (++index == items.length) index = 0;
+ if (index == putIndex) index = NONE;
return index;
}
@@ -1268,7 +1245,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
}
/**
- * Called whenever an interior remove (not at takeIndex) occured.
+ * Called whenever an interior remove (not at takeIndex) occurred.
*
* @return true if this iterator should be unlinked from itrs
*/
@@ -1277,17 +1254,18 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
if (isDetached())
return true;
- final int cycles = itrs.cycles;
final int takeIndex = ArrayBlockingQueue.this.takeIndex;
- final int prevCycles = this.prevCycles;
final int prevTakeIndex = this.prevTakeIndex;
final int len = items.length;
- int cycleDiff = cycles - prevCycles;
- if (removedIndex < takeIndex)
- cycleDiff++;
+ // distance from prevTakeIndex to removedIndex
final int removedDistance =
- (cycleDiff * len) + (removedIndex - prevTakeIndex);
- // assert removedDistance >= 0;
+ len * (itrs.cycles - this.prevCycles
+ + ((removedIndex < takeIndex) ? 1 : 0))
+ + (removedIndex - prevTakeIndex);
+ // assert itrs.cycles - this.prevCycles >= 0;
+ // assert itrs.cycles - this.prevCycles <= 1;
+ // assert removedDistance > 0;
+ // assert removedIndex != takeIndex;
int cursor = this.cursor;
if (cursor >= 0) {
int x = distance(cursor, prevTakeIndex, len);
@@ -1316,7 +1294,7 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
else if (x > removedDistance)
this.nextIndex = nextIndex = dec(nextIndex);
}
- else if (cursor < 0 && nextIndex < 0 && lastRet < 0) {
+ if (cursor < 0 && nextIndex < 0 && lastRet < 0) {
this.prevTakeIndex = DETACHED;
return true;
}
@@ -1354,4 +1332,5 @@ public class ArrayBlockingQueue<E> extends AbstractQueue<E>
// "remainingCapacity()=" + remainingCapacity());
// }
}
+
}