Loading...
Searching...
No Matches
QEventBus.hpp
Go to the documentation of this file.
#pragma once
#include <EASTL/functional.h>
#include <EASTL/unordered_map.h>
#include <EASTL/vector.h>
#include <EASTL/queue.h>
#include <EASTL/unique_ptr.h>
#include <typeindex>
#include <mutex>
#include "IEvent.hpp"
namespace mce::core {
struct SubscriptionToken {
eastl::function<void()> unsubscribe;
~SubscriptionToken() { if (unsubscribe)unsubscribe(); }
};
class QEventBus {
public:
QEventBus(const std::string_view& eventNamespace);
template<typename EventType>
using Handler = eastl::function<void(const EventType&)>;
template<typename EventType>
SubscriptionToken subscribeRAII(Handler<EventType> handler);
template<typename EventType>
void subscribe(Handler<EventType> handler);
template<typename EventType>
void post(EventType&& event);
void process();
void runAsync();
void stop();
size_t getQueueSize() const;
~QEventBus();
const std::string_view& getNamespace() const;
private:
void dispatch(const IEvent& e);
struct TypeIndexHash {
size_t operator()(const std::type_index& t) const noexcept {
return t.hash_code();
}
};
struct TypeIndexEqual {
bool operator()(const std::type_index& a, const std::type_index& b) const noexcept {
return a == b;
}
};
eastl::unordered_map<
std::type_index,
eastl::vector<eastl::function<void(const IEvent&)>>,
TypeIndexHash,
TypeIndexEqual
> handlers;
eastl::queue<eastl::unique_ptr<IEvent>> queue;
std::mutex mutex;
std::mutex queueMutex;
std::condition_variable conditionalVariable;
std::atomic_bool bIsRunning = false;
std::thread thread;
const std::string_view eventNamespace;
};
template<typename EventType>
inline SubscriptionToken QEventBus::subscribeRAII(Handler<EventType> handler) {
std::lock_guard<std::mutex> lock(QEventBus::mutex);
auto& handlers = QEventBus::handlers[typeid(EventType)];
handlers.emplace_back([handler](const IEvent& e) {
handler(static_cast<const EventType&>(e));
});
auto it = eastl::prev(handlers.end());
std::type_index typeIdx = std::type_index(typeid(EventType));
return SubscriptionToken{ [this, typeIdx, it]() {
std::lock_guard<std::mutex> lock(QEventBus::mutex);
auto mapIt = QEventBus::handlers.find(typeIdx);
if (mapIt != QEventBus::handlers.end()) {
auto& vec = mapIt->second;
vec.erase(it);
if (vec.empty()) {
QEventBus::handlers.erase(mapIt);
}
}
}
};
}
template<typename EventType>
inline void QEventBus::subscribe(Handler<EventType> handler) {
std::lock_guard<std::mutex> lock(QEventBus::mutex);
// Simply store the handler � no token or RAII logic.
auto& handlers = QEventBus::handlers[typeid(EventType)];
handlers.emplace_back([handler](const IEvent& e) {
handler(static_cast<const EventType&>(e));
});
}
template<typename EventType>
inline void QEventBus::post(EventType&& event) {
// Create an owned copy / move of the event on the heap
using Decayed = std::decay_t<EventType>;
auto ptr = eastl::make_unique<Decayed>(eastl::forward<EventType>(event));
{
std::lock_guard<std::mutex> lock(QEventBus::queueMutex);
QEventBus::queue.push(eastl::move(ptr));
}
QEventBus::conditionalVariable.notify_one();
}
}
mce::core::QEventBus::subscribe
void subscribe(Handler< EventType > handler)
Subscribe a handler to EventType without RAII token.
Definition QEventBus.hpp:246
mce::core::QEventBus::stop
void stop()
Stop asynchronous processing and join the worker thread.
Definition QEventBus.cpp:37
mce::core::QEventBus::runAsync
void runAsync()
Start asynchronous processing of queued events.
Definition QEventBus.cpp:18
mce::core::QEventBus::process
void process()
Process and dispatch all currently queued events.
Definition QEventBus.cpp:5
mce::core::QEventBus::post
void post(EventType &&event)
Post an event instance to the bus for later processing.
Definition QEventBus.hpp:257
mce::core::QEventBus::subscribeRAII
SubscriptionToken subscribeRAII(Handler< EventType > handler)
Subscribe a handler to EventType and receive a RAII token.
Definition QEventBus.hpp:217
mce::core::QEventBus::Handler
eastl::function< void(const EventType &)> Handler
Alias for an event handler function.
Definition QEventBus.hpp:69
mce::core::QEventBus::~QEventBus
~QEventBus()
Destructor.
Definition QEventBus.cpp:47
mce::IEvent
Definition IEvent.hpp:17
mce::core::SubscriptionToken
Token object that controls the lifetime of an event subscription.
Definition QEventBus.hpp:27
mce::core::SubscriptionToken::unsubscribe
eastl::function< void()> unsubscribe
Callable invoked to perform the unsubscribe action.
Definition QEventBus.hpp:33
mce::core::SubscriptionToken::~SubscriptionToken
~SubscriptionToken()
Destructor.
Definition QEventBus.hpp:40