/* ***************************************************************************+
 * ITX package (cnrg.itx) for telephony application programming.              *
 * Copyright (c) 1999  Cornell University, Ithaca NY                          *
 *                                                                            *
 * This program is free software; you can redistribute it and/or modify       *
 * it under the terms of the GNU General Public Liense as published by        *
 * the Free Software Foundation, either version 2 of the License, or (at      * 
 * your option) any later version.                                            *
 *                                                                            *
 * The ITX package is distributed in the hope that it will be useful, but     *
 * WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY *
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *
 * for more details.                                                          * 
 *                                                                            *
 * A copy of the license is distributed with this package.  Look in the docs  *
 * directory, filename GPL.                                                   *
 *                                                                            * 
 * Contact information:                                                       *
 * Donna Bergmark                                                             *
 * 484 Rhodes Hall                                                            *
 * Cornell University                                                         *
 * Ithaca, NY 14853-3801                                                      *
 * 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 */
