#pragma once #include #include #include #include #include #include #include namespace Dexode { class EventBus { public: EventBus() = default; ~EventBus() { _callbacks.clear(); } EventBus(const EventBus&) = delete; EventBus(EventBus&&) = delete; EventBus& operator=(EventBus&&) = delete; EventBus& operator=(const EventBus&) = delete; /** * Register listener for event. Returns token used for unlisten. * * @tparam Event - type you want to listen for * @param callback - your callback to handle event * @return token used for unlisten */ template int listen(const std::function& callback) { static_assert(Internal::validateEvent(), "Invalid event"); const int token = ++_tokener; listen(token, callback); return token; } /** * @tparam Event - type you want to listen for * @param token - unique token for identification receiver. Simply pass token from @see EventBus::listen * @param callback - your callback to handle event */ template void listen(const int token, const std::function& callback) { static_assert(Internal::validateEvent(), "Invalid event"); using Vector = Internal::TransactionCallbackVector; assert(callback && "callback should be valid"); //Check for valid object std::unique_ptr& vector = _callbacks[Internal::type_id()]; if(vector == nullptr) { vector.reset(new Vector {}); } assert(dynamic_cast(vector.get())); Vector* vectorImpl = static_cast(vector.get()); vectorImpl->add(token, callback); } /** * @param token - token from EventBus::listen */ void unlistenAll(const int token) { for(auto& element : _callbacks) { element.second->remove(token); } } /** * @tparam Event - type you want to unlisten. @see Notiier::listen * @param token - token from EventBus::listen */ template void unlisten(const int token) { static_assert(Internal::validateEvent(), "Invalid event"); auto found = _callbacks.find(Internal::type_id()); if(found != _callbacks.end()) { found->second->remove(token); } } /** * Notify all listeners for event * * @param event your event struct */ template void notify(const Event& event) { using CleanEventType = typename std::remove_const::type; static_assert(Internal::validateEvent(), "Invalid event"); using Vector = Internal::TransactionCallbackVector; auto found = _callbacks.find(Internal::type_id()); if(found == _callbacks.end()) { return; // no such notifications } std::unique_ptr& vector = found->second; assert(dynamic_cast(vector.get())); Vector* vectorImpl = static_cast(vector.get()); vectorImpl->beginTransaction(); for(const auto& element : vectorImpl->container) { element.second(event); } vectorImpl->commitTransaction(); } private: int _tokener = 0; std::map> _callbacks; }; } /* namespace Dexode */