import java.util.*;
import java.io.*;

public class Queue {
  private Vector queue = new Vector(100);
  // add and remove are synchronized using the queue object as a lock.
  // waitUntilEmpty and remove are synchronized using this object as a lock:
  // using the queue would cause interference with add/remove.
  private Object removalLock = new Object();
  
  public synchronized Object remove() {
    while(queue.isEmpty()) {
      try {
        wait();
      } catch(InterruptedException e) {}
    }
    Object item = queue.firstElement();
    queue.removeElement(item);
    if (isEmpty()) synchronized(removalLock) { removalLock.notifyAll(); }
    return item;
  }
  public synchronized void add(Object item) {
    queue.addElement(item);
    notifyAll();
  }
  /** Throws <code>NoSuchElementException</code> if the queue is empty. */
  public synchronized Object removeNB() {
    Object item = queue.firstElement();
    queue.removeElement(item);
    return item;
  }
  /** It blocks until the queue is empty. */
  public void waitUntilEmpty() {
    if (!queue.isEmpty()) 
      synchronized(removalLock) { 
        try{ 
          removalLock.wait(); 
        } catch(InterruptedException e) {}
      }
  }
  public synchronized void waitOnEmpty() {
    if (queue.isEmpty())
      try {
        wait();
      } catch(InterruptedException e) {}
  }
  public synchronized void removeElement (Object item) {
    queue.removeElement(item);
  }
  public Enumeration elements() { return queue.elements(); }
  public boolean isEmpty() { return queue.isEmpty(); }
  public int size() { return queue.size(); }
}
