summaryrefslogtreecommitdiff
path: root/src/CommonAPI/Event.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/CommonAPI/Event.h')
-rw-r--r--src/CommonAPI/Event.h197
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