Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <map>
- #include <vector>
- #include <functional>
- #include <algorithm> // remove and remove_if
- template <typename T> const uintptr_t class_id() {
- return reinterpret_cast<uintptr_t>(&class_id<T>);
- }
- template <typename T> class EventContainer {
- T m_Value;
- public:
- EventContainer(T value): m_Value(value) {}
- T get() {
- return this->m_Value;
- }
- };
- class IEventHandler {
- public:
- virtual uintptr_t id() = 0;
- virtual void handle_ptr(void* eventPtr) = 0;
- };
- template <typename T> class BaseEventHandler: public IEventHandler {
- public:
- uintptr_t id(){
- uintptr_t value = class_id<T>();
- return value;
- }
- void handle_ptr(void* eventPtr) {
- auto cast_eventPtr = static_cast<EventContainer<T>*>(eventPtr);
- this->handle(cast_eventPtr->get());
- }
- virtual void handle(T event) = 0;
- };
- template <typename T> class CallbackEventHandler : public BaseEventHandler<T> {
- std::function<void(T)> m_Callback;
- public:
- CallbackEventHandler(std::function<void(T)> callback): m_Callback(callback) {}
- void handle(T event) {
- this->m_Callback(event);
- }
- };
- class EventDispatcher{
- typedef std::map<uintptr_t, std::vector<IEventHandler*>> catalog_t;
- typedef EventDispatcher::catalog_t::iterator catalog_iterator_t;
- typedef std::vector<IEventHandler*> handler_catalog_t;
- EventDispatcher::catalog_t m_Catalogs;
- public:
- template <typename T> EventDispatcher::catalog_iterator_t getIteratorByType() {
- uintptr_t eventClassId = class_id<T>();
- auto it = this->m_Catalogs.find(eventClassId);
- if (it == this->m_Catalogs.end()) {
- this->m_Catalogs[eventClassId];
- return this->m_Catalogs.find(eventClassId);
- } else {
- return it;
- }
- }
- template <typename T> std::vector<IEventHandler*>& getHandlerByType() {
- EventDispatcher::catalog_iterator_t it = this->getIteratorByType<T>();
- return (*it).second;
- }
- template <typename T> void dispatch(T event) {
- auto handlers = this->getIteratorByType<T>()->second;
- auto eventContainer = EventContainer<T>(event);
- for(auto it = handlers.begin(); it != handlers.end(); ++it) {
- (*it)->handle_ptr(static_cast<void*>(&eventContainer));
- }
- }
- template <typename T> IEventHandler* on(std::function<void(T)> callback) {
- auto callbackContainer = new CallbackEventHandler<T>(callback);
- this->subscribe<T>(callbackContainer);
- return callbackContainer;
- }
- void unsubscribe(IEventHandler* handler) {
- auto class_id = handler->id();
- auto& handlers = this->m_Catalogs[class_id];
- handlers.erase(std::remove(handlers.begin(), handlers.end(), handler), handlers.end());
- }
- template <typename T>void subscribe(BaseEventHandler<T>* handler) {
- this->getHandlerByType<T>().push_back(handler);
- }
- };
- class BigEvent {};
- int main() {
- auto dispatcher = EventDispatcher();
- auto eventContainer = dispatcher.on<int>([] (int x) {
- std::cout << x << std::endl;
- });
- auto eventContainer2 = dispatcher.on<BigEvent>([] (BigEvent ev) {
- std::cout << "Big event incoming !!" << std::endl;
- });
- dispatcher.dispatch<int>(5);
- dispatcher.unsubscribe(eventContainer);
- dispatcher.dispatch(BigEvent());
- }
Add Comment
Please, Sign In to add comment