mql5/Include/Generic/Queue.mqh

420 lines
29 KiB
MQL5

2025-08-05 01:57:33 -04:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| Queue.mqh |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Generic\Interfaces\ICollection.mqh>
#include <Generic\Internal\ArrayFunction.mqh>
#include <Generic\Internal\EqualFunction.mqh>
//+------------------------------------------------------------------+
//| Class CQueue<T> |
//| Usage: Represents a first-in, first-out collection of objects |
//+------------------------------------------------------------------+
template<typename T>
class CQueue: public ICollection<T>
{
protected:
T m_array[];
int m_size; // items in queue
int m_head; // first valid element in the queue
int m_tail; // last valid element in the queue
public:
CQueue(void);
CQueue(const int capacity);
CQueue(ICollection<T>&collection[]);
CQueue(const T &array[]);
CQueue(const CQueue &queue);
~CQueue(void);
bool operator=(const CQueue &queue);
//--- methods of filling data
bool Add(T value) override;
bool Enqueue(T value);
//--- methods of access to protected data
int Count(void) override;
int Capacity(void) const;
bool Contains(T item) override;
bool SetCapacity(const int capacity);
void TrimExcess(double threshold_k=0.9);
//--- methods of copy data from collection
int CopyTo(T &dst_array[],const int dst_start=0) override;
//--- methods of cleaning and removing
void Clear(void) override;
bool Remove(T item) override;
bool Dequeue(T &item);
T Dequeue(void);
bool Peek(T &item) const;
T Peek(void) const;
};
//+------------------------------------------------------------------+
//| Initializes a new instance of the CQueue<T> class that is empty |
//| and has the default initial capacity |
//+------------------------------------------------------------------+
template<typename T> CQueue::CQueue(void): m_size(0),m_head(0),m_tail(0)
{
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CQueue<T> class that is empty |
//| and has the specified initial capacity or the default initial |
//| capacity, whichever is greater |
//+------------------------------------------------------------------+
template<typename T> CQueue::CQueue(const int capacity): m_size(0),m_head(0),m_tail(0)
{
ArrayResize(m_array,capacity);
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CQueue<T> class that contains |
//| elements copied from the specified array and has sufficient |
//| capacity to accommodate the number of elements copied |
//+------------------------------------------------------------------+
template<typename T> CQueue::CQueue(const T &array[]): m_head(0)
{
m_size=ArrayCopy(m_array,array);
m_tail=m_size;
}
//+------------------------------------------------------------------+
//| Initializes a new instance of the CQueue<T> class that contains |
//| elements copied from the specified collection and has sufficient |
//| capacity to accommodate the number of elements copied |
//+------------------------------------------------------------------+
template<typename T> CQueue::CQueue(ICollection<T>*collection): m_size(0),m_head(0)
{
//--- check collection
if(CheckPointer(collection)!=POINTER_INVALID)
m_size=collection.CopyTo(m_array);
//--- set tail
m_tail=m_size;
}
//+------------------------------------------------------------------+
//| Copy constructor |
//+------------------------------------------------------------------+
template<typename T> CQueue::CQueue(const CQueue &queue)
{
this=queue;
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
template<typename T> CQueue::~CQueue(void)
{
}
//+------------------------------------------------------------------+
//| Copy operator |
//+------------------------------------------------------------------+
template<typename T> bool CQueue::operator=(const CQueue &queue)
{
if(&this!=&queue)
{
m_size=0;
m_head=0;
m_tail=0;
if(!SetCapacity(queue.m_size))
return(false);
m_size=queue.m_size;
int size=ArraySize(queue.m_array);
for(int i=0; i<queue.m_size; i++)
m_array[i]=queue.m_array[(queue.m_head+i)%size];
}
return(true);
}
//+------------------------------------------------------------------+
//| Inserts an value at the top of the CQueue<T> |
//+------------------------------------------------------------------+
template<typename T>
bool CQueue::Add(T value)
{
return(Enqueue(value));
}
//+------------------------------------------------------------------+
//| Gets the number of elements |
//+------------------------------------------------------------------+
template<typename T>
int CQueue::Count(void)
{
return(m_size);
}
//+------------------------------------------------------------------+
//| Removes all values from the CQueue<T> |
//+------------------------------------------------------------------+
template<typename T>
bool CQueue::Contains(T item)
{
int size=ArraySize(m_array);
//--- try to find item in array
for(int i=m_head,const end=m_head+m_size; i<end; i++)
{
//--- use default equality function
if(::Equals(m_array[i%size],item))
return(true);
}
return(false);
}
//+------------------------------------------------------------------+
//| Sets the capacity to the actual number of elements in the queue, |
//| if that number is less than a threshold value |
//+------------------------------------------------------------------+
template<typename T>
void CQueue::TrimExcess(double threshold_k=0.9)
{
if(MathIsValidNumber(threshold_k) && threshold_k>0.0)
{
//--- calculate threshold value
int threshold=(int)(ArraySize(m_array)*MathMin(threshold_k,1.0));
//--- set a Aapacity equal to the size
if(m_size<threshold)
SetCapacity(m_size);
}
}
//+------------------------------------------------------------------+
//| Copies a range of elements from the queue to a compatible |
//| one-dimensional array |
//+------------------------------------------------------------------+
template<typename T>
int CQueue::CopyTo(T &dst_array[],const int dst_start=0)
{
//--- resize array
if((dst_start+m_size)>ArraySize(dst_array))
if(ArrayResize(dst_array,dst_start+m_size)<0)
return(0);
//--- copy queue elements from head to tail
if(m_tail>m_head)
return(ArrayCopy(dst_array,m_array,dst_start,m_head,m_size));
//--- copy queue elements from head to end
int num_copied=ArrayCopy(dst_array,m_array,dst_start,m_head,m_array.Size()-m_head);
//--- copy queue elements from beginning to tail
num_copied+=ArrayCopy(dst_array,m_array,dst_start+num_copied,0,m_tail);
//--- return number of copied elements
return(num_copied);
}
//+------------------------------------------------------------------+
//| Removes all values from the CQueue<T> |
//+------------------------------------------------------------------+
template<typename T>
void CQueue::Clear(void)
{
//--- check current size
if(m_size>0)
{
ArrayFree(m_array);
m_size=0;
m_head=0;
m_tail=0;