/* This file is part of Daydream Engine. Copyright 2014 Adam Byléhn, Tobias Dahl, Simon Holmberg, Viktor Ljung Daydream Engine is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Daydream Engine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Daydream Engine. If not, see . */ #ifndef MessageRelay_h__ #define MessageRelay_h__ #include #include #include #include #include #define EVENT_SUBSCRIBE_MEMBER(relay, handler) \ relay = decltype(relay)(std::bind(handler, this, std::placeholders::_1)); \ EventBroker->Subscribe(relay); namespace dd { struct Event { protected: Event() { } }; 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: 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 no matter the context. /*void Process() { }*/ /* Process all events in a given context. Returns: Number of events processed */ template int Process(); int Process(std::string contextTypeName); void Clear(); void Unsubscribe(BaseEventRelay &relay); template void UnsubscribeAll(); private: 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; typedef std::list>> EventQueue_t; std::shared_ptr m_EventQueueRead; std::shared_ptr m_EventQueueWrite; }; 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); } template void EventBroker::UnsubscribeAll() { const std::string contextTypeName = typeid(ContextType).name(); m_ContextRelays.erase(contextTypeName); } } #endif // MessageRelay_h__