#ifndef _CIRCULARQUEUE_H
#define _CIRCULARQUEUE_H
static char CircularQueue_h_id[] = "$Header: /usr/tiburon/xPlatform/utils/RCS/CircularQueue.h,v 1.3 1997/04/17 08:22:41 oreilly Exp pean $";

/*
$Log: CircularQueue.h,v $
Revision 1.3  1997/04/17 08:22:41  oreilly
Added comments

 * Revision 1.2  97/03/20  12:26:55  12:26:55  oreilly (Thomas C. O'Reilly)
 * *** empty log message ***
 * 
 * Revision 1.1  96/10/28  08:53:01  08:53:01  oreilly (Thomas C. O'Reilly)
 * Initial revision
 * 
*/


#include <mbari/types.h>
#include <mbari/const.h>
#include "ErrorHandler.h"
#include "malloc.h"

template<class T>
class CircularQueue : public ErrorHandler {

  public:
  CircularQueue(int maxQueueSize)
  {
    _maxQueueSize = maxQueueSize;
    if ((_array = (T *)malloc(maxQueueSize * sizeof(T))) == NULL)
    {
      char errorBuf[errorMsgSize];
      sprintf(errorBuf, "malloc() failed (%d bytes)", 
	      maxQueueSize * sizeof(T));

      setError(errorBuf);
      return;
    }
    clear();
  }
  
  ~CircularQueue()
  {
    free(_array);
  }

  // Return maximum size of queue
  int maxQueueSize()
  {
    return _maxQueueSize;
  }
  
  // Clear out queue contents
  void clear()
  {
    _head = _tail = _current = 0;
    _wrapped = FALSE; 
  }

  // Add element to end of queue
  void add(T *val)
  {
    _array[_tail] = *val;

    if (++_tail >= _maxQueueSize)
    {
      _wrapped = TRUE;
      _tail = 0;
    }
    
    if (_wrapped)
    {
      if (++_head >= _maxQueueSize)
	_head = 0;
    }
  }

  // Start queue iterator
  void startIter()
  {
    _current = _head;
  }
  

  // Get next element of queue
  T* next()
  {
    if (_current == _tail)
      return NULL;
    else
    {
      T *ptr = &_array[_current];
      if (++_current >= _maxQueueSize)
	_current = 0;

      return ptr;
    }
  }

  // Return number of elements currently in queue
  int length()
  {
    if (_wrapped)
      return _maxQueueSize;
    else
      return _tail - _head;
  }
  
  protected:

  T* _array; 
  int _maxQueueSize;
  int _head;
  int _tail;
  int _current;
  MBool _wrapped;
};
  
#endif
