Collections Data Structure Java

/**
 * The utillib library.
 * More information is available at http://www.jinchess.com/.
 * Copyright (C) 2002 Alexander Maryanovsky.
 * All rights reserved.
 *
 * The utillib library is free software; you can redistribute
 * it and/or modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * The utillib library 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 Lesser
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with utillib library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
import java.util.Enumeration;
import java.util.Vector;
/**
 * 

A blocking queue, one that always "contains" elements.
 * If it is in fact empty, the pop() and peek() method will block until an
 * item is pushed.
 * 

NOTE: This class is thread safe.
 *
 * @author Alexander Maryanovsky.
 */
public class BlockingQueue implements Cloneable{
  /**
   * The underlying Vector this BlockingQueue is using.
   */
  private final Vector queue;
  /**
   * The lock we use to synchronize pushing.
   */
  private final Object pushLock = new String("BlockingQueue pushLock");
  /**
   * The lock we use to synchronize popping.
   */
  private final Object popLock = new String("BlockingQueue popLock");
  /**
   * Creates a new, empty BlockingQueue.
   */
  public BlockingQueue(){
    queue = new Vector();
  }
  /**
   * Pushes an element into the queue.
   */
  public void push(Object object){
    synchronized(pushLock){
      queue.addElement(object);
      synchronized(this){
        notify();
      }
    }
  }
  /**
   * Pops an element from the queue. If the queue is empty, this method blocks
   * until another thread pushes an element into the queue.
   *
   * @throws InterruptedException if the invoking thread was interrupted
   * while waiting for an element to be pushed into the queue.
   */
  public Object pop() throws InterruptedException{
    return pop(0);
  }
  /**
   * Pops an element from the queue. Unlike the pop() method, this method does not block
   * for longer than the given amount of milliseconds. When the given amount of milliseconds
   * have passed, this method will throw an InterruptedException.
   */
  public Object pop(long timeout) throws InterruptedException{
    synchronized(popLock){
      synchronized(this){
        if (queue.isEmpty()){
          wait(timeout);
          if (queue.isEmpty())
            throw new InterruptedException("Timed out");
        }
      }
      Object val = queue.firstElement();
      queue.removeElementAt(0);
      return val;
    }
  }
  /**
   * Returns the element on top of the queue without popping it. If the queue
   * is empty, this method blocks until another thread pushes an element into
   * the queue.
   *
   * @throws InterruptedException if the invoking thread was interrupted while
   * waiting for an element to be pushed into the queue.
   */
  public Object peek() throws InterruptedException{
    return peek(0);
  }
  /**
   * Returns the element on top of the queue without popping it.
   * Unlike the peek() method, this method does not block
   * for longer than the given amount of milliseconds. When the given amount of milliseconds
   * have passed, this method will throw an InterruptedException.
   */
  public Object peek(long timeout) throws InterruptedException{
    synchronized(popLock){
      synchronized(this){
        if (queue.isEmpty()){
          wait(timeout);
          if (queue.isEmpty())
            throw new InterruptedException("Timed out");
        }
      }
      return queue.firstElement();
    }
  }
  /**
   * Returns true if the queue is empty (this returns the actual state of the
   * queue, meaning it may return true even though ideologically, a BlockingQueue
   * is never empty).
   */
  public boolean isEmpty(){
    return queue.isEmpty();
  }
  /**
   * Returns true if the given element is in the queue.
   */
  public boolean contains(Object element){
    return queue.contains(element);
  }
  /**
   * Returns the size of the queue.
   */
  public int size(){
    return queue.size();
  }
  /**
   * Returns an Enumeration of the elements in this queue. The order of the
   * elements is the same as if they were popped from the queue one by one (the
   * first element is the first element that would have been popped). 

   * IMPORTANT: Modifying the queue breaks the returned Enumeration.
   */
  public Enumeration getElements(){
    return queue.elements();
  }
  /**
   * Removes all elements from this queue.
   */
  public void removeAllElements(){
    queue.removeAllElements();
  }
  /**
   * Removes all elements from this queue.
   */
  public void clear(){
    queue.removeAllElements();
  }
  /**
   * Returns a shallow copy of this BlockingQueue.
   */
  public synchronized Object clone(){
    BlockingQueue copy = new BlockingQueue();
    Enumeration elems = getElements();
    while (elems.hasMoreElements()){
      Object item = elems.nextElement();
      copy.push(item);
    }
    return copy;
  }
}