/** the queued items **/
final object[] items;
/** items index for next take, poll, peek or remove **/
int takeindex;
/** items index for next put, offer, or add **/
int putindex;
/** number of elements in the queue **/
int count;
/**
* concurrency control uses the classic two-condition algorithm
* found in any textbook.
**/
/** main lock guarding all access **/
final reentrantlock lock;
/** condition for waiting takes **/
private final condition notempty;
/** condition for waiting puts **/
private final condition notfull;
/**
* shared state for currently active iterators, or null if there
* are known not to be any. allows queue operations to update
* iterator state.
**/
transient itrs itrs = null;
/**
* inserts the specified element at the tail of this queue, waiting
* for space to become available if the queue is full.
* @throws interruptedexception {@inheritdoc}
* @throws nullpointerexception {@inheritdoc}
**/
public void put(e e) throws interruptedexception {
checknotnull(e);
final reentrantlock lock = this.lock;
lock.lockinterruptibly();
try {
while (count == items.length)
notfull.await();
enqueue(e);
} finally {
lock.unlock();
}
}
/**
* 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;
if (++putindex == items.length)
putindex = 0;
count++;
notempty.signal();
}
/**
* inserts the specified element at the tail of this queue if it is
* possible to do so immediately without exceeding the queue's capacity,
* returning {@code true} upon success and {@code false} if this queue
* is full. this method is generally preferable to method {@link #add},
* which can fail to insert an element only by throwing an exception.
* @throws nullpointerexception if the specified element is null
**/
public boolean offer(e e) {
checknotnull(e);
final reentrantlock lock = this.lock;
lock.lock();
try {
if (count == items.length)
return false;
else {
enqueue(e);
return true;
}
} finally {
lock.unlock();
}
}