/** * Bounded buffer with synchronization. */ package csci3366sample.bbuf; public class BoundedBuffer { /* store as circular queue in array */ private T[] buffer; private int nextToRemove; private int numElements; private boolean verbose; @SuppressWarnings("unchecked") public BoundedBuffer(int sz, boolean verbose) { buffer = (T[]) new Object[sz]; nextToRemove = 0; numElements = 0; this.verbose = verbose; } /** * Print message if "verbose" flag on. */ private void verbosePrint(String msg) { if (verbose) System.out.println("**"+msg); } /** * Put item into buffer. * Waits if buffer is full. * Allows exceptions thrown by wait() to bubble up. */ public synchronized void put(T item) throws InterruptedException { verbosePrint("starting put with numElements = " + numElements); /* wait until not full */ while (numElements == buffer.length) wait(); int next = (nextToRemove + numElements) % buffer.length; buffer[next] = item; ++numElements; /* * wake up all waiting threads (just in case some are waiting * for "buffer not empty") */ notifyAll(); verbosePrint("ending put with numElements = " + numElements); } /** * Get item from buffer. * Waits if buffer is empty. * Allows exceptions thrown by wait() to bubble up. * @return item */ public synchronized T get() throws InterruptedException { verbosePrint("starting get with numElements = " + numElements); /* wait until not empty */ while (numElements == 0) wait(); T item = buffer[nextToRemove]; nextToRemove = (nextToRemove + 1) % buffer.length; --numElements; /* * wake up all waiting threads (just in case some are waiting * for "buffer not full") */ notifyAll(); verbosePrint("ending get with numElements = " + numElements); return item; } /** * Check if buffer is empty. */ public synchronized boolean isEmpty() { return (numElements == 0); } }