#pragma once #include #include #include #include #include #include #include #include #include enum class EventType { Echo, ChunkChanged, }; struct EchoData { std::chrono::time_point time; }; struct ChunkChangedData { Vector chunkPosition; }; using EventData = std::variant; struct Event { EventType type; EventData data; }; class EventListener { friend class EventAgregator; using HandlerFunc = std::function; std::map handlers; //TODO: There must be more elegant solution than std::variant of all data std::mutex eventsMutex; std::queue events; void PushEvent(Event event); public: EventListener(); ~EventListener(); bool IsEventsQueueIsNotEmpty(); void RegisterHandler(EventType type, HandlerFunc handler) { handlers[type] = handler; } void HandleEvent() { eventsMutex.lock(); if (events.empty()) { eventsMutex.unlock(); return; } Event event = events.front(); events.pop(); eventsMutex.unlock(); auto function = handlers[event.type]; function(event.data); } }; class EventAgregator { friend EventListener; EventAgregator() = default; static std::queue eventsToHandle; static std::mutex queueMutex; static bool isStarted; static std::vector listeners; static std::mutex listenersMutex; static void EventHandlingLoop(); static void RegisterListener(EventListener &listener); static void UnregisterListener(EventListener &listener); public: static void PushEvent(EventType type, EventData data) { if (!isStarted) { isStarted = true; std::thread(&EventAgregator::EventHandlingLoop).detach(); } Event event; event.type = type; event.data = data; eventsToHandle.push(event); } };