// $Id: Queue.java,v 1.3 2009/10/22 14:40:37 leavens Exp leavens $
/** A primitive concurrent Queue of Objects, used to demonstrate
 * concurrency features of Java, including synchronized methods, the
 * wait method, and the notifyAll method.
 * @author Gary T. Leavens
 */
public class Queue<T> {
    private int SIZE = 10;
    /** the elements in the queue. */
    private final T[] elems;
    /** the number of elements currently in the queue. */
    private int numElems = 0;
    /** where to put the next element */
    private int toPut = 0;
    /** where to get the next element */
    private int toGet = 0;

    @SuppressWarnings("unchecked") // to stop warnings from the body...
    public Queue() {
        // Java disallows elems = new T[SIZE]; since T isn't around at runtime
        elems = (T[]) new Object[SIZE];
    }

    /** Put the argument in the Queue, or wait if no space is available. */
    public synchronized void put(T x) {
        while (numElems >= SIZE) {
            try {
                wait();
            } catch (InterruptedException e) {
                // ignore it
            }
        }
        //@ assert numElems < SIZE;
        elems[toPut] = x;
        toPut = (toPut+1) % SIZE;
        numElems++;
        notifyAll();
    }

    /** Get the next element in the Queue, or wait if none are available. */
    public synchronized T get() {
        while (numElems == 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                // ignore it
            }
        }
        //@ assert numElems > 0;
        T ret = elems[toGet];
        toGet = (toGet+1) % SIZE;
        numElems--;
        notifyAll();
        return ret;
    }
}

