mql5/Experts/_FrameWork/Events/EventBus/EventBus.mqh

132 lines
3.7 KiB
MQL5

2026-09-30 09:06:59 +02:00
//+------------------------------------------------------------------+
//| EventBus.mqh |
//| Copyright 2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include "AbstractEvent.mqh"
#include "IEventListener.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class EventBus
{
private:
// Subscription record
struct Subscription
{
EventType type;
IEventListener* listener;
};
// Circular buffer for event pointers
AbstractEvent* m_queue[512];
int m_head;
int m_tail;
// Dynamic array of subscriptions
Subscription m_subscriptions[];
int m_subCount;
// Find index of a specific subscription, or -1
int FindSubscription(EventType type, IEventListener* listener) const
{
for(int i = 0; i < m_subCount; i++)
{
if(m_subscriptions[i].type == type && m_subscriptions[i].listener == listener)
return i;
}
return -1;
}
public:
EventBus() : m_head(0), m_tail(0), m_subCount(0) {}
// Subscribe a listener for a specific event type
void Subscribe(EventType type, IEventListener* listener)
{
if(FindSubscription(type, listener) >= 0)
return; // already subscribed
int size = ArraySize(m_subscriptions);
ArrayResize(m_subscriptions, size + 1);
m_subscriptions[size].type = type;
m_subscriptions[size].listener = listener;
m_subCount = size + 1;
}
// Unsubscribe
void Unsubscribe(EventType type, IEventListener* listener)
{
int idx = FindSubscription(type, listener);
if(idx < 0)
return;
// Shift remaining elements
for(int i = idx; i < m_subCount - 1; i++)
m_subscriptions[i] = m_subscriptions[i + 1];
m_subCount--;
ArrayResize(m_subscriptions, m_subCount);
}
bool IsEmpty() const { return m_head == m_tail; }
bool IsFull() const { return ((m_tail + 1) % 512) == m_head; }
// Push an event (takes ownership of the pointer)
void Push(AbstractEvent* event)
{
if(IsFull())
{
delete event;
return;
}
m_queue[m_tail] = event;
m_tail = (m_tail + 1) % 512;
}
void Dispatch()
{
while(!IsEmpty())
{
AbstractEvent* event = m_queue[m_head];
m_head = (m_head + 1) % 512;
EventType type = event.GetType();
int matchCount = 0;
for(int i = 0; i < m_subCount; i++)
{
if(m_subscriptions[i].type == type)
{
matchCount++;
m_subscriptions[i].listener.OnEvent(event);
}
}
delete event;
}
}
// Clean up any remaining events (e.g., on shutdown)
void Clear()
{
while(!IsEmpty())
{
AbstractEvent* event = m_queue[m_head];
m_head = (m_head + 1) % 512;
delete event;
}
}
~EventBus()
{
Clear();
}
};
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+