132 lines
3.7 KiB
MQL5
132 lines
3.7 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| 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();
| |
}
| |
};
| |
//+------------------------------------------------------------------+
| |
//+------------------------------------------------------------------+
|