/
ScryMUD/mud/
ScryMUD/mud/grrmud/Boards/
ScryMUD/mud/grrmud/Help/
ScryMUD/mud/grrmud/Pfiles/
ScryMUD/mud/grrmud/PlayerSacks/
ScryMUD/mud/grrmud/PlayerShops/
ScryMUD/mud/grrmud/help_filter/
ScryMUD/mud/hegemon/
ScryMUD/mud/hegemon/data/
ScryMUD/mud/hegemon/data/help/battle/
ScryMUD/mud/hegemon/data/help/client/
ScryMUD/mud/hegemon/data/help/communications/
ScryMUD/mud/hegemon/data/help/skills/
ScryMUD/mud/hegemon/data/help/spells/
ScryMUD/mud/include/
ScryMUD/mud/lib/
ScryMUD/mud/lib/bitfield/
ScryMUD/mud/lib/log/
ScryMUD/mud/lib/string2/
// $Id: Queue.java,v 1.3 1999/06/05 23:29:12 greear Exp $
// $Revision: 1.3 $  $Author: greear $ $Date: 1999/06/05 23:29:12 $

//
//Hegemon Client Code:  Java Client for ScryMUD Server Code
//Copyright (C) 1998  Ben Greear
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either version 2
//of the License, or (at your option) any later version.
//
//This program 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.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// To contact the Author, Ben Greear:  greear@cyberhighway.net, (preferred)
//                                     greearb@agcs.com
//


import java.util.*;

/**  Head points to the next slot to add an element to.
  Tail points to the slot just before oldest element.
  If (previous index of head) == tail, then the queue is empty.
  NOTE:  this queue wastes one space, but this gives us a lot
  more simplicity in keeping track of is-full and is_empty status.
  */

class Queue extends Object {
   int head_idx;
   int tail_idx;
   int len;
   Object[] vect;

   public Queue(int length) {
      super();
      len = length + 1; /* we waste a space for simplicity */
      head_idx = 0;
      tail_idx = len;
      vect = new Object[len]; /* 0 --> double capacity if needed */
   }//constructor

   /** Return an array of Objects contained in the queue.  The
     oldest elements are at the lower indexes of the returned array.. */
   public final synchronized Object[] getArray() {
      int my_len = this.length();
      int my_idx = tail_idx;
      Object[] retval = new Object[my_len];

      Log.instance().dbg("Queue: In getArray(), my_len:  " + my_len);
      for (int i = 0; i < my_len; i++) {
         retval[i] = vect[my_idx = getNextIdx(my_idx)];
      }//for
      return retval;
   }//getArray
   
   /**  Add an object to the head of the queue, will throw an
     Exception if its already full. */
   public final synchronized void push(Object obj) throws Exception {
      //Log.it("Queue:  in push");
      if (!this.isFull()) {
         vect[head_idx] = obj;
         head_idx = getNextIdx(head_idx);
      }
      else {
         throw new Exception("ERROR:  Queue is full.");
      }
   }//push

   /**  Remove and return the oldest object from the queue.  Throws
    Exception if it's empty. */
   public final synchronized Object pull() throws Exception {
      if (!isEmpty()) {
         tail_idx = getNextIdx(tail_idx);
         return vect[tail_idx];
      }
      else {
         throw new Exception("ERROR:  Queue is empty.");
      }
   }//pull

   public final void keepNewest(int cnt) {
      int to_junk_cnt = (length() - cnt);
      for (int i = 0; i<to_junk_cnt; i++) {
         try {
            pull();
         }
         catch (Exception e) {
            Log.instance().err("Queue::keepNewest, cnt:  " + cnt + "  " + e);
         }//catch
      }//for
   }//keepNewest

   /** returns the oldest object, but DOES NOT REMOVE IT
     from the queue. Throws exception if its empty. */
   public final synchronized Object peek() throws Exception {
      if (!isEmpty()) {
         return vect[getNextIdx(tail_idx)];
      }
      else {
         throw new Exception("ERROR:  Queue is empty.");
      }
   }//pull

   private final int getNextIdx(int idx) {
      if (idx == len) {
         return 0;
      }
      else {
         return idx + 1;
      }
   }//getNextIdx

   private final int getPrevIdx(int idx) {
      if (idx == 0)
         return len;
      else
         return idx - 1;
   }//getPrevIdx

   /**  Test the empty-ness of the queue. */
   public final boolean isEmpty() {
      if (getPrevIdx(head_idx) == tail_idx)
        return true;
      else
         return false;
   }//isEmpty

   /**  Test the fullness of the queue. */
   public final boolean isFull() {
      if (tail_idx == head_idx)
        return true;
      else
        return false;
   }//isFull

   /**  Return the number of elements found in the queue.  Could
    allow for a cheaper method of cleaning out the array (ie don't have
    to test for isEmpty all the time..) */

   public final int length() {
      if (tail_idx >= head_idx) {
         return head_idx + (len - tail_idx);
      }//if
      else {
         return head_idx - tail_idx;
      }
   }//length

   public final int capacity() {
      return len - 1; //we waste a space, but is much more convenient!
   }
}//Queue