package com.github.rfqu.ringBuffer.blockingQueues; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class RingBuffer<T> { int bufSize; Object[] entries; WindowQueue writeQueue; WindowQueue readQueue; final Lock lock = new ReentrantLock(); final Condition posChanged = lock.newCondition(); public RingBuffer(int bufSize) { this.bufSize = bufSize; entries=new Object[bufSize]; writeQueue=new WriteQueue(); readQueue=new ReadQueue(); } abstract class WindowQueue { long lowLimit; long position; private long putWaitCount; private long takeWaitCount; public void put(T element) throws InterruptedException { lock.lock(); try { while (getHiLimit()==position) { putWaitCount++; posChanged.await(); } entries[(int)(position%bufSize)]=element; position++; posChanged.signal(); } finally { lock.unlock(); } } @SuppressWarnings("unchecked") public T take() throws InterruptedException { lock.lock(); try { while (position==lowLimit) { takeWaitCount++; posChanged.await(); } posChanged.signal(); return (T)entries[(int)(lowLimit++%bufSize)]; } finally { lock.unlock(); } } abstract long getHiLimit(); } class ReadQueue extends WindowQueue { @Override long getHiLimit() { return writeQueue.lowLimit+bufSize; } } class WriteQueue extends WindowQueue { long getHiLimit() { return readQueue.lowLimit; } } abstract class Cursor { public abstract void put(T element) throws InterruptedException; public abstract T take() throws InterruptedException; public abstract long getPutWaitCount(); public abstract long getTakeWaitCount(); } public class Writer extends Cursor { @Override public void put(T element) throws InterruptedException { writeQueue.put(element); } @Override public T take() throws InterruptedException { return readQueue.take(); } public long getPutWaitCount() { return writeQueue.putWaitCount; } public long getTakeWaitCount() { return readQueue.takeWaitCount; } } public class Reader extends Cursor { @Override public void put(T element) throws InterruptedException { readQueue.put(element); } @Override public T take() throws InterruptedException { return writeQueue.take(); } public long getPutWaitCount() { return readQueue.putWaitCount; } public long getTakeWaitCount() { return writeQueue.takeWaitCount; } } }