#ifndef EventBroker_h__ #define EventBroker_h__ #include #include #include #include #include #include "../Common.h" #include "Event.h" #define EVENT_SUBSCRIBE_MEMBER(relay, handler) \ relay = decltype(relay)(std::bind(handler, this, std::placeholders::_1)); \ m_EventBroker->Subscribe(relay); typedef unsigned int EventID; class EventBroker; class BaseEventRelay { friend class EventBroker; protected: BaseEventRelay(std::string contextTypeName, std::string eventTypeName) : m_ContextTypeName(contextTypeName) , m_EventTypeName(eventTypeName) , m_Broker(nullptr) { } ~BaseEventRelay(); public: virtual bool Receive(const std::shared_ptr event) = 0; protected: EventID m_EventID; std::string m_ContextTypeName; std::string m_EventTypeName; EventBroker* m_Broker; }; template class EventRelay : public BaseEventRelay { public: typedef std::function CallbackType; EventRelay() : m_Callback(nullptr) , BaseEventRelay(typeid(ContextType).name(), typeid(EventType).name()) { } EventRelay(CallbackType callback) : m_Callback(callback) , BaseEventRelay(typeid(ContextType).name(), typeid(EventType).name()) { } protected: bool Receive(const std::shared_ptr event) override; private: CallbackType m_Callback; }; template bool EventRelay::Receive(const std::shared_ptr event) { if (m_Callback != nullptr) { return m_Callback(*static_cast(event.get())); } else { return false; } } class EventBroker { template friend class EventRelay; public: EventBroker() { m_EventQueueRead = std::make_shared(); m_EventQueueWrite = std::make_shared(); } void Subscribe(BaseEventRelay &relay); template void Publish(const EventType &event); /* Process all events in a given context. Returns: Number of events processed */ template int Process(); int Process(std::string contextTypeName); void Swap(); void Clear(); void Unsubscribe(BaseEventRelay &relay); private: bool m_IsProcessing = false; EventID m_NextEventID = 0; typedef std::string ContextTypeName_t; // typeid(ContextType).name() typedef std::string EventTypeName_t; // typeid(EventType).name() typedef std::unordered_multimap EventRelays_t; typedef std::unordered_map ContextRelays_t; ContextRelays_t m_ContextRelays; std::vector m_RelaysToSubscribe; std::unordered_map> m_RelaysToUnsubscribe; typedef std::list>> EventQueue_t; std::shared_ptr m_EventQueueRead; std::shared_ptr m_EventQueueWrite; void subscribeImmediate(BaseEventRelay& relay); void unsubscribeImmediate(std::tuple identifier); }; template void EventBroker::Publish(const EventType &event) { /*auto itpair = m_Subscribers.equal_range(typeid(EventType).name()); for (auto it = itpair.first; it != itpair.second; ++it) { it->second->Receive(event); }*/ m_EventQueueWrite->push_back(std::make_pair(typeid(EventType).name(), std::shared_ptr(new EventType(event)))); } template int EventBroker::Process() { const std::string contextTypeName = typeid(ContextType).name(); return Process(contextTypeName); } #endif