From fa32e7a9f46c7da39a527d0ebc049e3720068d8e Mon Sep 17 00:00:00 2001 From: LaG1924 <12997935+LaG1924@users.noreply.github.com> Date: Fri, 29 Dec 2017 17:09:51 +0500 Subject: Implemented new event system --- src/Event.hpp | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) (limited to 'src/Event.hpp') diff --git a/src/Event.hpp b/src/Event.hpp index 3f59c93..752fda4 100644 --- a/src/Event.hpp +++ b/src/Event.hpp @@ -1,2 +1,132 @@ #pragma once +#include +#include +#include +#include +#include +#include +#include + + +size_t constexpr StrHash(char const *input) { + return *input ? static_cast(*input) + 33 * StrHash(input + 1) : 5381; +} + +class Event { + struct EventDataBase { + virtual ~EventDataBase() {} + virtual const std::type_info& Type() const = 0; + }; + + template + struct EventData : EventDataBase { + EventData(const T &val) : data(val) {} + + const std::type_info& Type() const override { + return typeid(data); + } + + T data; + }; + + std::shared_ptr data; + +public: + const size_t id; + + template + Event(size_t eventId, const T &value) : + id(eventId), + data(std::make_shared>(value)) {} + + ~Event() = default; + + Event(const Event &other) = default; + + Event &operator=(const Event &) = default; + + Event(Event &&) = delete; + + Event &operator=(Event &&) = delete; + + template + const T& get() const { + if (typeid(T) != data->Type()) + throw std::runtime_error(std::string("Type ") + typeid(T).name() + " encountered but " + data->Type().name() + " expected"); + return static_cast*>(data.get())->data; + } +}; + +class EventListener { + friend class EventSystem; + using HandlerType = std::function; + std::queue events; + std::map handlers; + std::mutex eventsQueueMutex; + std::mutex handlersMutex; +public: + EventListener(); + + ~EventListener(); + + void HandleEvent(); + + void HandleAllEvents(); + + bool NotEmpty(); + + void WaitEvent(); + + void RegisterHandler(size_t eventId, const HandlerType &data) { + std::lock_guard lock(handlersMutex); + handlers[eventId] = data; + } + + void RegisterHandler(const char *eventId, const HandlerType & data) { + RegisterHandler(StrHash(eventId), data); + } +}; + +class EventSystem { + friend class EventListener; + static std::list listeners; + static std::mutex listenersMutex; + +public: + template + static void PushEvent(size_t eventId, T data) { + Event event(eventId, data); + + std::lock_guard listenersLock(listenersMutex); + for (auto& listener : listeners) { + std::lock_guard lock(listener->eventsQueueMutex); + std::lock_guard lockHandlers(listener->handlersMutex); + auto it = listener->handlers.find(eventId); + if (it == listener->handlers.end()) + continue; + + listener->events.push(event); + } + } + + template + static void DirectEventCall(size_t eventId, T data) { + Event event(eventId, data); + + std::lock_guard listenersLock(listenersMutex); + for (auto & listener : listeners) { + std::lock_guard lock(listener->eventsQueueMutex); + std::lock_guard lockHandlers(listener->handlersMutex); + auto it = listener->handlers.find(eventId); + if (it == listener->handlers.end()) + continue; + + it->second(event); + } + } +}; + +#define PUSH_EVENT(eventName, data) EventSystem::PushEvent(StrHash(eventName),data) + +#define DIRECT_EVENT_CALL(eventName,data) EventSystem::DirectEventCall(StrHash(eventName),data) \ No newline at end of file -- cgit v1.2.3