#pragma once #include #include #include #include #include #include #include "Event.h" #include "EventHandler.h" /** * \class EventManager * \brief The EventManager class is responsible for managing the subscription, triggering, * and queueing of events. It handles events and dispatches them to appropriate subscribers. */ class EventManager { public: /** * \brief Deleted copy constructor to prevent copying of the EventManager instance. */ EventManager(const EventManager &) = delete; /** * \brief Deleted copy assignment operator to prevent assignment of the EventManager instance. */ const EventManager & operator=(const EventManager &) = delete; /** * \brief Get the singleton instance of the EventManager. * * This method returns the unique instance of the EventManager, creating it on the first call. * * \return Reference to the EventManager instance. */ static EventManager & get_instance(); /** * \brief Subscribe to an event. * * This method allows the registration of a callback for a specific event type and channel. * * \tparam EventType The type of the event to subscribe to. * \param callback The callback function to invoke when the event is triggered. * \param channel The channel number to subscribe to (default is 0). */ template void subscribe(EventHandler && callback, int channel = 0); /** * \brief Unsubscribe from an event. * * This method removes a previously registered callback from an event. * * \tparam EventType The type of the event to unsubscribe from. * \param callback The callback function to remove from the subscription list. * \param channel The event ID to unsubscribe from. */ template void unsubscribe(const EventHandler &, int channel); /** * \brief Trigger an event. * * This method invokes the appropriate callback(s) for the specified event. * * \tparam EventType The type of the event to trigger. * \param event The event data to pass to the callback. * \param channel The channel from which to trigger the event (default is 0). */ template void trigger_event(const EventType & event, int channel); /** * \brief Queue an event for later processing. * * This method adds an event to the event queue, which will be processed in the * dispatch_events function. * * \tparam EventType The type of the event to queue. * \param event The event to queue. * \param channel The channel number for the event (default is 0). */ template void queue_event(EventType&& event, int channel); /** * \brief Dispatch all queued events. * * This method processes all events in the event queue and triggers the corresponding * callbacks for each event. */ void dispatch_events(); private: /** * \brief Default constructor for the EventManager. * * This constructor is private to enforce the singleton pattern. */ EventManager() = default; //! The queue of events to be processed. std::vector, int, std::type_index>> events_queue; //! Registered event handlers. std::unordered_map>> subscribers; //! Event handlers indexed by event ID. std::unordered_map>>> subscribers_by_event_id; }; template void EventManager::subscribe(EventHandler && callback, int channel) { std::type_index event_type = typeid(EventType); std::unique_ptr> handler = std::make_unique>(callback); if (channel) { std::unordered_map>>& handlers_map = this->subscribers_by_event_id[event_type]; std::unordered_map>>::iterator handlers = handlers_map.find(channel); if (handlers != handlers_map.end()) { handlers->second.emplace_back(std::move(handler)); } else { handlers_map[channel].emplace_back(std::move(handler)); } } else { std::vector>& handlers = this->subscribers[event_type]; handlers.emplace_back(std::move(handler)); } } template void EventManager::queue_event(EventType&& event, int channel) { std::type_index event_type = std::type_index(typeid(EventType)); std::unique_ptr event_ptr = std::make_unique(std::forward(event)); std::tuple, int, std::type_index> tuple( std::move(event_ptr), channel, event_type ); this->events_queue.push_back(std::move(tuple)); } template void EventManager::trigger_event(const EventType & event, int channel) { std::type_index event_type = std::type_index(typeid(EventType)); if (channel > 0) { std::unordered_map>>& handlers_map = this->subscribers_by_event_id[event_type]; std::unordered_map>>::iterator handlers_it = handlers_map.find(channel); if (handlers_it != handlers_map.end()) { std::vector>& handlers = handlers_it->second; for (std::vector>::iterator it = handlers.begin(); it != handlers.end();) { // erases callback if callback function returns true if ((*it)->exec(event)) { it = handlers.erase(it); } else { ++it; } } } } else { std::vector>& handlers = this->subscribers[event_type]; for (std::vector>::iterator it = handlers.begin(); it != handlers.end();) { // erases callback if callback function returns true if ((*it)->exec(event)) { it = handlers.erase(it); } else { ++it; } } } } template void EventManager::unsubscribe(const EventHandler & callback, int channel) { std::type_index event_type(typeid(EventType)); std::string handler_name = callback.target_type().name(); if (channel) { std::unordered_map>>>::iterator subscriber_list = this->subscribers_by_event_id.find(event_type); if (subscriber_list != this->subscribers_by_event_id.end()) { std::unordered_map>>& handlers_map = subscriber_list->second; std::unordered_map>>::iterator handlers = handlers_map.find(channel); if (handlers != handlers_map.end()) { std::vector>& callbacks = handlers->second; for (std::vector>::iterator it = callbacks.begin(); it != callbacks.end(); ++it) { if ((*it)->get_type() == handler_name) { it = callbacks.erase(it); return; } } } } } else { std::unordered_map>>::iterator handlers_it = this->subscribers.find(event_type); if (handlers_it != this->subscribers.end()) { std::vector>& handlers = handlers_it->second; for (std::vector>::iterator it = handlers.begin(); it != handlers.end(); ++it) { if ((*it)->get_type() == handler_name) { it = handlers.erase(it); return; } } } } }