/*
 * Aleph Toolkit
 *
 * Copyright 1998, Brown University, Providence, RI.
 * 
 *                         All Rights Reserved
 * 
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose other than its incorporation into a
 * commercial product is hereby granted without fee, provided that the
 * above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Brown University not be used in
 * advertising or publicity pertaining to distribution of the software
 * without specific, written prior permission.
 * 
 * BROWN UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ANY
 * PARTICULAR PURPOSE.  IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE FOR
 * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package aleph.comm.udp;

/**
 * Synchronized FIFO packet queue.
 * @see aleph.comm.datagram.Packet
 *
 * @author Maurice Herlihy
 * @date   August 1997
 **/

public class PacketQueue {
  Packet head = null;
  Packet tail = null;
  public String toString() {
    Packet packet = head;
    StringBuffer answer = new StringBuffer("PacketQueue[");
    while (packet != null) {
      answer.append(" ");
      answer.append(packet.toString());
      packet = packet.next;
    }
    answer.append("]");
    return answer.toString();
  }

  /**
   * @return <code>true</code> iff queue contains no packets.
   **/
  public synchronized boolean empty() {
    return head == null;
  }

  /**
   * Splice list of packets at tail of queue.
   * @param packet Head of Packet list.
   **/
  public synchronized void enq(Packet packet) {
    if (head == null) { 		// empty queue
      head = packet;
      tail = packet;
    } else {
      tail.next = packet;	// non-empty
      tail = packet;
    }
    notifyAll();		// goose the dequeuers
  }

  /**
   * @return next Packet.  Blocks if none available.
   **/
  public synchronized Packet deq() {
    while (head == null) {
      try {wait();} catch (InterruptedException e) {}
    }
    Packet result = head;	// grab it
    head   = head.next;		// next in line
    result.next = null;		// unlink
    if (head == null)		// did we empty the queue?
      tail = null;
    return result;
  }

}

