diff options
Diffstat (limited to 'src/CommonAPI/Event.h')
-rw-r--r-- | src/CommonAPI/Event.h | 193 |
1 files changed, 0 insertions, 193 deletions
diff --git a/src/CommonAPI/Event.h b/src/CommonAPI/Event.h deleted file mode 100644 index 3d059b2..0000000 --- a/src/CommonAPI/Event.h +++ /dev/null @@ -1,193 +0,0 @@ -/* Copyright (C) 2013 BMW Group - * Author: Manfred Bathelt (manfred.bathelt@bmw.de) - * Author: Juergen Gehring (juergen.gehring@bmw.de) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#if !defined (COMMONAPI_INTERNAL_COMPILATION) -#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef COMMONAPI_EVENT_H_ -#define COMMONAPI_EVENT_H_ - -#include <functional> -#include <list> -#include <tuple> -#include <mutex> - -namespace CommonAPI { - -enum class SubscriptionStatus { - RETAIN, - CANCEL -}; - -/** - * \brief Class representing an event - * - * Class representing an event - */ -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 - */ - virtual Subscription subscribe(Listener listener); - - /** - * \brief Subscribe a cancellable listener to this event - * - * Subscribe a cancellable 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 cancellable listener to be added - * @return A token identifying this subscription - */ - 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); - - virtual ~Event() { - } - -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 unsubscribe() - virtual void onListenerRemoved(const CancellableListener& listener) { } - virtual void onLastListenerRemoved(const CancellableListener& listener) { } - - inline bool hasListeners() const; - -//private: - ListenersList listenersList_; - std::mutex listenerListMutex_; -}; - -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_; -}; - -template<typename ... _Arguments> -typename Event<_Arguments...>::Subscription Event<_Arguments...>::subscribe(Listener listener) { - return subscribeCancellableListener(CancellableListenerWrapper(std::move(listener))); -} - -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(); - - if (firstListenerAdded) { - onFirstListenerAdded(*listenerSubscription); - } - - onListenerAdded(*listenerSubscription); - - return listenerSubscription; -} - -template<typename ... _Arguments> -void Event<_Arguments...>::unsubscribe(Subscription listenerSubscription) { - const CancellableListener cancellableListener = *listenerSubscription; - - listenerListMutex_.lock(); - listenersList_.erase(listenerSubscription); - const bool lastListenerRemoved = listenersList_.empty(); - listenerListMutex_.unlock(); - - onListenerRemoved(cancellableListener); - - if (lastListenerRemoved) { - onLastListenerRemoved(cancellableListener); - } -} - -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...); - - if (listenerSubscriptionStatus == SubscriptionStatus::CANCEL) { - auto listenerIterator = iterator; - iterator++; - listenersList_.erase(listenerIterator); - } else - iterator++; - } - - const bool lEmpty = listenersList_.empty(); - - listenerListMutex_.unlock(); - - return lEmpty ? SubscriptionStatus::CANCEL : SubscriptionStatus::RETAIN; -} - -template<typename ... _Arguments> -bool Event<_Arguments...>::hasListeners() const { - return !listenersList_.empty(); -} - -} // namespace CommonAPI - -#endif // COMMONAPI_EVENT_H_ |