diff options
Diffstat (limited to 'src/CommonAPI/Event.h')
-rw-r--r-- | src/CommonAPI/Event.h | 197 |
1 files changed, 101 insertions, 96 deletions
diff --git a/src/CommonAPI/Event.h b/src/CommonAPI/Event.h index b032da9..9cac1dc 100644 --- a/src/CommonAPI/Event.h +++ b/src/CommonAPI/Event.h @@ -20,8 +20,8 @@ namespace CommonAPI { enum class SubscriptionStatus { - RETAIN, - CANCEL + RETAIN, + CANCEL }; /** @@ -29,33 +29,33 @@ enum class SubscriptionStatus { * * Class representing an event */ -template <typename... _Arguments> +template<typename ... _Arguments> class Event { - public: - typedef std::tuple<_Arguments...> ArgumentsTuple; - typedef std::function<void(const _Arguments&...)> Listener; - typedef std::function<SubscriptionStatus(const _Arguments&...)> CancellableListener; - typedef std::list<CancellableListener> ListenersList; - typedef typename ListenersList::iterator Subscription; - - class CancellableListenerWrapper; - - /** - * \brief Subscribe a listener to this event - * - * Subscribe a listener to this event. - * ATTENTION: You should not build new proxies or register services in callbacks - * from events. This can cause a deadlock or assert. Instead, you should set a - * trigger for your application to do this on the next iteration of your event loop - * if needed. The preferred solution is to build all proxies you need at the - * beginning and react to events appropriatly for each. - * - * @param listener A listener to be added - * @return A token identifying this subscription - */ - inline Subscription subscribe(Listener listener); - - /** +public: + typedef std::tuple<_Arguments...> ArgumentsTuple; + typedef std::function<void(const _Arguments&...)> Listener; + typedef std::function<SubscriptionStatus(const _Arguments&...)> CancellableListener; + typedef std::list<CancellableListener> ListenersList; + typedef typename ListenersList::iterator Subscription; + + class CancellableListenerWrapper; + + /** + * \brief Subscribe a listener to this event + * + * Subscribe a listener to this event. + * ATTENTION: You should not build new proxies or register services in callbacks + * from events. This can cause a deadlock or assert. Instead, you should set a + * trigger for your application to do this on the next iteration of your event loop + * if needed. The preferred solution is to build all proxies you need at the + * beginning and react to events appropriatly for each. + * + * @param listener A listener to be added + * @return A token identifying this subscription + */ + virtual inline Subscription subscribe(Listener listener); + + /** * \brief Subscribe a cancellable listener to this event * * Subscribe a cancellable listener to this event @@ -68,119 +68,124 @@ class Event { * @param listener A cancellable listener to be added * @return A token identifying this subscription */ - Subscription subscribeCancellableListener(CancellableListener listener); + Subscription subscribeCancellableListener(CancellableListener listener); - /** + /** * \brief Remove a listener from this event * * Remove a listener from this event * Note: Do not call this inside a listener notification callback it will deadlock! Use cancellable listeners instead. * * @param listenerSubscription A listener token to be removed + * @return true, if the removed subscription was the last one */ - void unsubscribe(Subscription listenerSubscription); + void unsubscribe(Subscription listenerSubscription); - virtual ~Event() {} + virtual ~Event() { + } - protected: - // Returns false if all subscriptions were cancelled - // Does not send *Removed events! - SubscriptionStatus notifyListeners(const _Arguments&... eventArguments); +protected: + // Returns false if all subscriptions were cancelled + // Does not send *Removed events! + SubscriptionStatus notifyListeners(const _Arguments&... eventArguments); - // Events sent during subscribe() - virtual void onFirstListenerAdded(const CancellableListener& listener) { } - virtual void onListenerAdded(const CancellableListener& listener) { } + // Events sent during subscribe() + virtual void onFirstListenerAdded(const CancellableListener& listener) { + } + virtual void onListenerAdded(const CancellableListener& listener) { + } - // Events sent during unsubscribe() - virtual void onListenerRemoved(const CancellableListener& listener) { } - virtual void onLastListenerRemoved(const CancellableListener& listener) { } + // Events sent during unsubscribe() + virtual void onListenerRemoved(const CancellableListener& listener) { } + virtual void onLastListenerRemoved(const CancellableListener& listener) { } - inline bool hasListeners() const; + inline bool hasListeners() const; - private: - ListenersList listenersList_; - std::mutex listenerListMutex_; +//private: + ListenersList listenersList_; + std::mutex listenerListMutex_; }; -template <typename... _Arguments> +template<typename ... _Arguments> class Event<_Arguments...>::CancellableListenerWrapper { - public: - CancellableListenerWrapper(Listener&& listener): listener_(std::move(listener)) { - } - - SubscriptionStatus operator()(const _Arguments&... eventArguments) { - listener_(eventArguments...); - return SubscriptionStatus::RETAIN; - } - - private: - Listener listener_; +public: + CancellableListenerWrapper(Listener&& listener) : + listener_(std::move(listener)) { + } + + SubscriptionStatus operator()(const _Arguments&... eventArguments) { + listener_(eventArguments...); + return SubscriptionStatus::RETAIN; + } + +private: + Listener listener_; }; -template <typename... _Arguments> +template<typename ... _Arguments> typename Event<_Arguments...>::Subscription Event<_Arguments...>::subscribe(Listener listener) { - return subscribeCancellableListener(CancellableListenerWrapper(std::move(listener))); + return subscribeCancellableListener(CancellableListenerWrapper(std::move(listener))); } -template <typename... _Arguments> +template<typename ... _Arguments> typename Event<_Arguments...>::Subscription Event<_Arguments...>::subscribeCancellableListener(CancellableListener listener) { listenerListMutex_.lock(); const bool firstListenerAdded = listenersList_.empty(); - listenersList_.emplace_front(std::move(listener)); - Subscription listenerSubscription = listenersList_.begin(); - listenerListMutex_.unlock(); + listenersList_.emplace_front(std::move(listener)); + Subscription listenerSubscription = listenersList_.begin(); + listenerListMutex_.unlock(); - if (firstListenerAdded) { - onFirstListenerAdded(*listenerSubscription); - } + if (firstListenerAdded) { + onFirstListenerAdded(*listenerSubscription); + } - onListenerAdded(*listenerSubscription); + onListenerAdded(*listenerSubscription); - return listenerSubscription; + return listenerSubscription; } -template <typename... _Arguments> +template<typename ... _Arguments> void Event<_Arguments...>::unsubscribe(Subscription listenerSubscription) { - const CancellableListener cancellableListener = *listenerSubscription; + const CancellableListener cancellableListener = *listenerSubscription; - listenerListMutex_.lock(); - listenersList_.erase(listenerSubscription); - const bool lastListenerRemoved = listenersList_.empty(); - listenerListMutex_.unlock(); + listenerListMutex_.lock(); + listenersList_.erase(listenerSubscription); + const bool lastListenerRemoved = listenersList_.empty(); + listenerListMutex_.unlock(); - onListenerRemoved(cancellableListener); + onListenerRemoved(cancellableListener); - if (lastListenerRemoved) { - onLastListenerRemoved(cancellableListener); - } + if (lastListenerRemoved) { + onLastListenerRemoved(cancellableListener); + } } -template <typename... _Arguments> +template<typename ... _Arguments> SubscriptionStatus Event<_Arguments...>::notifyListeners(const _Arguments&... eventArguments) { - listenerListMutex_.lock(); - for (auto iterator = listenersList_.begin(); iterator != listenersList_.end(); ) { - const CancellableListener& cancellableListener = *iterator; - const SubscriptionStatus listenerSubscriptionStatus = cancellableListener(eventArguments...); + listenerListMutex_.lock(); + for (auto iterator = listenersList_.begin(); iterator != listenersList_.end();) { + const CancellableListener& cancellableListener = *iterator; + const SubscriptionStatus listenerSubscriptionStatus = cancellableListener(eventArguments...); - if (listenerSubscriptionStatus == SubscriptionStatus::CANCEL) { - auto listenerIterator = iterator; - iterator++; - listenersList_.erase(listenerIterator); - } else - iterator++; - } + if (listenerSubscriptionStatus == SubscriptionStatus::CANCEL) { + auto listenerIterator = iterator; + iterator++; + listenersList_.erase(listenerIterator); + } else + iterator++; + } - const bool lEmpty = listenersList_.empty(); + const bool lEmpty = listenersList_.empty(); - listenerListMutex_.unlock(); + listenerListMutex_.unlock(); - return lEmpty ? SubscriptionStatus::CANCEL : SubscriptionStatus::RETAIN; + return lEmpty ? SubscriptionStatus::CANCEL : SubscriptionStatus::RETAIN; } -template <typename... _Arguments> +template<typename ... _Arguments> bool Event<_Arguments...>::hasListeners() const { - return !listenersList_.empty(); + return !listenersList_.empty(); } } // namespace CommonAPI |