Skip to content

Commit 8e4f747

Browse files
committed
Initial Commit
1 parent 7633322 commit 8e4f747

13 files changed

Lines changed: 974 additions & 40 deletions

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ set(COMPONENT_ADD_INCLUDEDIRS
88

99
register_component()
1010

11-
target_compile_options(${COMPONENT_TARGET} PRIVATE -fno-rtti)
11+
target_compile_options(${COMPONENT_TARGET} PRIVATE -frtti)

src/ESPressio_Event.hpp

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,70 @@
1-
#pragma once
1+
#pragma once
2+
3+
#include <cstdint>
4+
5+
#include <ESPressio_ThreadSafe.hpp>
6+
7+
#include "ESPressio_IEvent.hpp"
8+
#include "ESPressio_EventEnums.hpp"
9+
#include "ESPressio_EventManager.hpp"
10+
11+
using namespace ESPressio::Base;
12+
using namespace ESPressio::Threads;
13+
14+
namespace ESPressio {
15+
16+
namespace Event {
17+
18+
class Event : public IEvent {
19+
private:
20+
ReadWriteMutex<unsigned long> _dispatchTime = ReadWriteMutex<unsigned long>(0);
21+
Mutex<uint32_t> _refCount = Mutex<uint32_t>(0);
22+
bool _wasDispatched = false;
23+
public:
24+
virtual ~Event() { }
25+
26+
inline void __ref() override {
27+
_refCount.WithWriteLock([](uint32_t& refCount) {
28+
refCount++;
29+
});
30+
}
31+
32+
inline void __unref() override {
33+
uint32_t cnt = 99;
34+
_refCount.WithWriteLock([&cnt](uint32_t& refCount) {
35+
refCount--;
36+
cnt = refCount;
37+
});
38+
if (cnt == 0) { delete this; }
39+
}
40+
41+
inline void __dispatch() override {
42+
if (_wasDispatched) { return; }
43+
_wasDispatched = true;
44+
_dispatchTime.WithWriteLock([](unsigned long& dispatchTime) {
45+
if (dispatchTime == 0) {
46+
dispatchTime = millis();
47+
}
48+
});
49+
}
50+
51+
void Queue(EventPriority priority = EventPriority::Normal) override {
52+
EventManager::GetInstance()->QueueEvent(this, priority);
53+
}
54+
55+
void Stack(EventPriority priority = EventPriority::Normal) override {
56+
EventManager::GetInstance()->StackEvent(this, priority);
57+
}
58+
59+
inline unsigned long GetDispatchTime() override {
60+
return _dispatchTime.Get();
61+
}
62+
63+
inline unsigned long GetTimeSinceDispatch() override {
64+
return millis() - _dispatchTime.Get();
65+
}
66+
};
67+
68+
}
69+
70+
}

src/ESPressio_EventDispatcher.hpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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+
}

src/ESPressio_EventEnums.hpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#pragma once
2+
3+
#include <functional>
4+
5+
6+
namespace ESPressio {
7+
8+
namespace Event {
9+
10+
enum EventPriority {
11+
Low = 0,
12+
Normal = 1,
13+
High = 2
14+
};
15+
16+
// ++ operator for EventPriority to move to the next value (and roll over to the beginning if at the end)
17+
inline EventPriority& operator++(EventPriority& priority) {
18+
priority = static_cast<EventPriority>((static_cast<int>(priority) + 1) % 3);
19+
return priority;
20+
}
21+
22+
// -- operator for EventPriority to move to the previous value (and roll over to the end if at the beginning)
23+
inline EventPriority& operator--(EventPriority& priority) {
24+
priority = static_cast<EventPriority>((static_cast<int>(priority) + 2) % 3);
25+
return priority;
26+
}
27+
28+
enum EventListenerInterest {
29+
All,
30+
YoungerThan,
31+
Custom
32+
};
33+
34+
// ++ operator for EventListenerInterest to move to the next value (and roll over to the beginning if at the end)
35+
inline EventListenerInterest& operator++(EventListenerInterest& interest) {
36+
interest = static_cast<EventListenerInterest>((static_cast<int>(interest) + 1) % 4);
37+
return interest;
38+
}
39+
40+
// -- operator for EventListenerInterest to move to the previous value (and roll over to the end if at the beginning)
41+
inline EventListenerInterest& operator--(EventListenerInterest& interest) {
42+
interest = static_cast<EventListenerInterest>((static_cast<int>(interest) + 3) % 4);
43+
return interest;
44+
}
45+
46+
enum EventDispatchMethod {
47+
Stack,
48+
Queue
49+
};
50+
51+
// ++ operator for EventDispatchMethod to move to the next value (and roll over to the beginning if at the end)
52+
inline EventDispatchMethod& operator++(EventDispatchMethod& method) {
53+
method = static_cast<EventDispatchMethod>((static_cast<int>(method) + 1) % 2);
54+
return method;
55+
}
56+
57+
// -- operator for EventDispatchMethod to move to the previous value (and roll over to the end if at the beginning)
58+
inline EventDispatchMethod& operator--(EventDispatchMethod& method) {
59+
method = static_cast<EventDispatchMethod>((static_cast<int>(method) + 1) % 2);
60+
return method;
61+
}
62+
63+
}
64+
65+
}
66+
67+
using namespace ESPressio::Event;
68+
69+
// Hash specialization for EventPriority enum
70+
// This enables `EventPriority` to be used as a Key in any set or map type.
71+
namespace std {
72+
template <>
73+
struct hash<EventPriority> {
74+
std::size_t operator()(const EventPriority& priority) const {
75+
return std::hash<int>()(static_cast<int>(priority));
76+
}
77+
};
78+
}

src/ESPressio_EventHandler.hpp

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/ESPressio_EventListener.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include "ESPressio_EventListener.hpp"
2+
3+
#include <functional>
4+
5+
namespace ESPressio {
6+
7+
namespace Event {
8+
9+
template <typename EventType>
10+
IEventListenerHandler* IEventListener::RegisterListener(
11+
std::function<void(
12+
IEvent*,
13+
EventDispatchMethod dispatchMethod,
14+
EventPriority priority)> callback,
15+
EventListenerInterest interest,
16+
unsigned long maximumTimeSinceDispatch,
17+
std::function<bool(IEvent*)> customInterestCallback
18+
) {
19+
return RegisterListener(typeid(EventType), callback, interest, maximumTimeSinceDispatch, customInterestCallback);
20+
}
21+
22+
template <typename EventType>
23+
void IEventListener::UnregisterListener(IEventListenerHandler* handler) {
24+
UnregisterListener(typeid(EventType), handler);
25+
}
26+
27+
}
28+
29+
}

0 commit comments

Comments
 (0)