1+ #pragma once
2+
3+ #include < vector>
4+ #include < unordered_map>
5+ #include < mutex>
6+
7+ #include " ESPressio_IEvent.hpp"
8+ #include " ESPressio_EventReceiver.hpp"
9+
10+ namespace ESPressio {
11+
12+ namespace Event {
13+
14+ /*
15+ `IEventDispatcher` is an interface that defines the methods that an event dispatcher should implement.
16+ Event Dispatchers act as both an `IEventReceiver`, and an Event-Typed Collection of other `IEventReceiver` objects.
17+ Their job is to facilitate the transit of Events from one `IEventReceiver` to another.
18+ This is essential for the Event Engine to function.
19+ */
20+ class IEventDispatcher {
21+ public:
22+ virtual ~IEventDispatcher () { }
23+ // / Registers an `IEventReceiver` to receive Events of a specific type from this `IEventDispatcher`.
24+ virtual void RegisterReceiver (std::type_index type, IEventReceiver* receiver) = 0;
25+ // / Unregisters an `IEventReceiver` from receiving Events of a specific type from this `IEventDispatcher`.
26+ virtual void UnregisterReceiver (std::type_index type, IEventReceiver* receiver) = 0;
27+ };
28+
29+ // / `EventDispatcher` is a concrete implementation of the `IEventDispatcher` interface.
30+ class EventDispatcher : public EventReceiver , public IEventDispatcher {
31+ private:
32+ typedef std::vector<IEventReceiver*> EventReceiverBucket;
33+ typedef std::unordered_map<std::type_index, EventReceiverBucket*> EventReceiverTypeMap;
34+
35+ EventReceiverTypeMap _eventReceivers;
36+ std::mutex _eventReceiversMutex; // It's necessary because we're using a shared resource (the `_eventReceivers` map) across multiple threads.
37+
38+ // / BEWARE: This method doesn't lock the `_eventReceiversMutex`! It's the caller's responsibility to lock it!
39+ EventReceiverBucket* GetEventTypeBucket (std::type_index type) {
40+ if (_eventReceivers.find (type) == _eventReceivers.end ()) {
41+ _eventReceivers[type] = new EventReceiverBucket ();
42+ }
43+ return _eventReceivers[type];
44+ }
45+ protected:
46+ void ClearEventReceivers () {
47+ _eventReceiversMutex.lock ();
48+ for (auto it = _eventReceivers.begin (); it != _eventReceivers.end (); it++) {
49+ delete it->second ;
50+ }
51+ _eventReceivers.clear ();
52+ _eventReceiversMutex.unlock ();
53+ }
54+
55+ void DispatchEvents () {
56+ _eventReceiversMutex.lock ();
57+
58+ WithEvents ([&](IEvent* event, EventDispatchMethod dispatchMethod, EventPriority priority) {
59+ std::type_index type = typeid (*event);
60+ EventReceiverBucket* bucket = GetEventTypeBucket (type);
61+ bool wasHandled = false ;
62+ for (IEventReceiver* receiver : *bucket) {
63+ if (dispatchMethod == EventDispatchMethod::Queue) {
64+ receiver->QueueEvent (event, priority);
65+ } else {
66+ receiver->StackEvent (event, priority);
67+ }
68+ event->__unref ();
69+ wasHandled = true ;
70+ }
71+ if (!wasHandled) { event->__unref (); }
72+ });
73+
74+ _eventReceiversMutex.unlock ();
75+ }
76+ public:
77+ EventDispatcher () { }
78+
79+ virtual ~EventDispatcher () override {
80+ ClearEventReceivers ();
81+ }
82+
83+ void RegisterReceiver (std::type_index type, IEventReceiver* receiver) override {
84+ _eventReceiversMutex.lock ();
85+ EventReceiverBucket* bucket = GetEventTypeBucket (type);
86+ for (IEventReceiver* r : *bucket) {
87+ if (r == receiver) {
88+ _eventReceiversMutex.unlock ();
89+ return ;
90+ }
91+ }
92+ bucket->push_back (receiver);
93+ _eventReceiversMutex.unlock ();
94+ }
95+
96+ void UnregisterReceiver (std::type_index type, IEventReceiver* receiver) override {
97+ _eventReceiversMutex.lock ();
98+ EventReceiverBucket* bucket = GetEventTypeBucket (type);
99+ for (auto it = bucket->begin (); it != bucket->end (); it++) {
100+ if (*it == receiver) {
101+ bucket->erase (it);
102+ _eventReceiversMutex.unlock ();
103+ return ;
104+ }
105+ }
106+ _eventReceiversMutex.unlock ();
107+ }
108+ };
109+
110+ }
111+
112+ }
0 commit comments