package com.github.rfqu.ringBuffer.blockingQueues; class RingBufferSync<T> { int bufSize; Object[] entries; WindowQueue writeQueue; WindowQueue readQueue; public RingBufferSync(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 { synchronized(RingBufferSync.this) { while (getHiLimit()==position) { putWaitCount++; RingBufferSync.this.wait(); } entries[(int)(position%bufSize)]=element; position++; RingBufferSync.this.notifyAll(); } } @SuppressWarnings("unchecked") public T take() throws InterruptedException { synchronized(RingBufferSync.this) { while (position==lowLimit) { takeWaitCount++; RingBufferSync.this.wait(); } RingBufferSync.this.notifyAll(); return (T)entries[(int)(lowLimit++%bufSize)]; } } 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; } } }