/* ***************************************************************************+
 * ITX package (cnrg.itx) for telephony application programming.              *
 * Copyright (c) 1999  Cornell University, Ithaca NY.                         *
 * A copy of the license is distributed with this package.  Look in the docs  *
 * directory, filename GPL.  Contact information: bergmark@cs.cornell.edu     *
 ******************************************************************************/


package cnrg.itx.datax.jaudio;

import java.util.*;
import java.io.*;

/** Queue Class */
class Queue
{
	QueueElement mHead = null;			// the head of the queue
	QueueElement mTail = null;
	int	mNumElements = 0;

	/**
	 * WaitAndPop()
	 */
	public synchronized Object WaitAndPop()
	{
		try
		{
			if(mHead == null)
			{
				this.wait();
			}
			return Pop();
		}
		catch(Exception e)
		{
			// Print some error out here :)
			System.out.println("Queue.WaitAndPop() wait threw exception: " + e);
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * Push() - <<QueueElement>>
	 */
	public synchronized boolean Push(QueueElement obj)
	{
		try
		{
			// if queue is empty then fill it
			if((mHead == null)&&(mTail == null))
			{
				//Replaces the new ElementInternal(obj)
				obj.SetObject(obj);
				mHead = obj;
				mTail = mHead;
				this.notify();
				mNumElements++;
				return true;
			}
			else
			{
				// o.w. move tail back

				//Replaces the new ElementInternal(obj)
				obj.SetObject(obj);

				mTail.SetNext(obj);
				mTail = mTail.GetNext();
				this.notify();
				mNumElements++;
				return true;
			}
		}
		catch(Exception e)
		{
			// Print some error out here :)
			System.out.println("Queue.Push() notify() threw exception: " + e);
			e.printStackTrace();
			return false;
		}		
	}

	/**
	 * Push()  <<OBJECT>>
	 */
	public synchronized boolean Push(Object obj)
	{
		try
		{
			// if queue is empty then fill it
			if((mHead == null)&&(mTail == null))
			{
				mHead = new ElementInternal(obj);
				mTail = mHead;
				this.notify();
				mNumElements++;
				return true;
			}
			else
			{
				// o.w. move tail back
				mTail.SetNext(new ElementInternal(obj));
				mTail = mTail.GetNext();
				this.notify();
				mNumElements++;
				return true;
			}
		}
		catch(Exception e)
		{
			// Print some error out here :)
			System.out.println("Queue.Push() notify() threw exception: " + e);
			e.printStackTrace();
			return false;
		}		
	}



	/**
	 * Pop()
	 */
	public synchronized Object Pop()
	{
		QueueElement temp = mHead;

		// if queue is empty
		if((mHead == null)&&(mTail == null))
		{
			return null;
		}
		// o.w. return something
		if(mHead == mTail)
		{
			mHead.SetNext(null);
			mHead = null;
			mTail = null;
		}
		else
		{
			mHead = mHead.GetNext();
			temp.SetNext(null);
		}

		mNumElements--;
		return temp.GetObject();
	}

	/**
	 * IsEmpty()
	 */
	public synchronized boolean IsEmpty()
	{
		return ((mHead == null)&&(mTail == null));
	}

	/**
	 * Size()
	 */
	public synchronized int Size()
	{
		return mNumElements;
	}

	/**
	 * Close() --> Wakes up any thread waiting on the queue.
	 */
	public synchronized void Close()
	{
		mHead = null;
		mTail = null;
		this.notify();			
	}

}/** end class Queue */

/** Element class */
class ElementInternal extends QueueElement
{
	ElementInternal(Object obj)
	{
		SetObject(obj);
		SetNext(null);
	}
}/** end class Element */
