/**
 * Shared buffer that stores integers and enforces mutual exclusion.
 *   @author Dave Reed
 *   @version 4/12/17
 */
public class Buffer {
    private int [] buffer;
    private int numStored, putIndex, getIndex;

    /**
     * Constructs an empty buffer of the specified size.
     *   @param size the buffer size
     */
    public Buffer(int size) {
        this.buffer = new int[size];
        this.numStored = 0;
        this.putIndex = 0;
        this.getIndex = 0;
    }

    /**
     * Puts a number into the buffer (ensuring mutual exclusion)
     *   @param task the number to be stored
     */
    public synchronized void put(int task) {
        while(this.numStored == this.buffer.length) {
            try { wait(); }
            catch (InterruptedException e) { } 
        }       
        this.buffer[this.putIndex] = task; 
        this.putIndex = (this.putIndex + 1) % this.buffer.length; 
        this.numStored++; 
        notify(); 
    }

    /**
     * Gets the next number from the buffer (ensuring mutual exclusion)
     *   return the retrieved number
     */
    public synchronized int get() {
        while (this.numStored == 0) {
            try { wait(); }
            catch (InterruptedException e) { } 
        } 
        int task = this.buffer[this.getIndex]; 
        this.getIndex = (this.getIndex + 1) % this.buffer.length;
        this.numStored--;
        notify(); 
        return task;
    }

   
   /////////////////////////////////////////////////
   
   public static void main(String [] args)
   {
      Buffer b = new Buffer(4);
      Producer p = new Producer(b);
      Consumer c = new Consumer(b);

      p.start();
      c.start();
   }
}