public class ConditionBoundedBuffer<T> {
private final T[] buffer;
private int tail, head, count;
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
public ConditionBoundedBuffer(int size) {
this.buffer = (T[]) new Object[size];
}
public void put(T e) throws InterruptedException {
try {
lock.lock();
while (isFull())
notFull.await();
putInternal(e);
notEmpty.signal();
} finally {
lock.unlock();
}
}
public T take() throws InterruptedException {
try {
lock.lock();
while (isEmpty())
notEmpty.await();
T result = takeInternal();
notFull.signal();
return result;
} finally {
lock.unlock();
}
}
private void putInternal(T e) {
buffer[tail] = e;
count++;
tail = (tail + 1) % buffer.length;
}
private T takeInternal() {
T result = buffer[head];
buffer[head] = null;
count--;
head = (head + 1) % buffer.length;
return result;
}
private boolean isFull() {
return count >= buffer.length;
}
private boolean isEmpty() {
return count <= 0;
}
}