From 681a586ae917af525adea5c633c2dfead14fca49 Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Fri, 14 Feb 2020 07:32:17 +0100 Subject: [PATCH] util-event: Rest of fb5041a69d0f264176b537926c1922abfc295c33 --- source/util-event.hpp | 164 ++++++++++++++++++++++++++---------------- 1 file changed, 104 insertions(+), 60 deletions(-) diff --git a/source/util-event.hpp b/source/util-event.hpp index 09160296..ec2f9e59 100644 --- a/source/util-event.hpp +++ b/source/util-event.hpp @@ -25,105 +25,149 @@ namespace util { template class event { - std::list> listeners; - std::recursive_mutex lock; + std::list> _listeners; + std::recursive_mutex _lock; - std::function listen_cb; - std::function silence_cb; + std::function _cb_fill; + std::function _cb_clear; - public /* functions */: - - // Destructor + public /* constructor */: + event() : _listeners(), _lock(), _cb_fill(), _cb_clear() {} virtual ~event() { - std::lock_guard lock; + std::lock_guard lg(_lock); this->clear(); } - // Add new listener. - inline void add(std::function listener) - { - std::lock_guard lock; - if (listeners.size() == 0) { - if (listen_cb) { - listen_cb(); - } - } - listeners.push_back(listener); - } + /* Copy Constructor */ + event(const event<_args...>&) = delete; - // Remove existing listener. - inline void remove(std::function listener) + /* Move Constructor */ + event(event<_args...>&& other) : event() { - std::lock_guard lock; - listeners.remove(listener); - if (listeners.size() == 0) { - if (silence_cb) { - silence_cb(); - } - } - } + std::lock_guard lg(_lock); + std::lock_guard lg(other._lock); - // Check if empty / no listeners. - inline bool empty() - { - std::lock_guard lock; - return listeners.empty(); - } - - // Remove all listeners. - inline void clear() - { - std::lock_guard lock; - listeners.clear(); - if (silence_cb) { - silence_cb(); - } + _listeners.swap(other._listeners); + _cb_fill.swap(other._cb_fill); + _cb_clear.swap(other._cb_clear); } public /* operators */: - // Call Listeners with arguments. - /// Not valid without the extra template. + + /* Copy Operator */ + event<_args...>& operator=(const event<_args...>&) = delete; + + /* Move Operator */ + event<_args...>& operator=(event<_args...>&& other) + { + std::lock_guard lg(_lock); + std::lock_guard lgo(other._lock); + + _listeners.swap(other._listeners); + _cb_fill.swap(other._cb_fill); + _cb_clear.swap(other._cb_clear); + + return *this; + } + + /** Call the event, going through all listeners in the order they were registered in. + */ template inline void operator()(_args... args) { - std::lock_guard lock; - for (auto& l : listeners) { + call<_largs...>(args...); + } + template + inline void call(_args... args) + { + std::lock_guard lg(_lock); + for (auto& l : _listeners) { l(args...); } } - // Convert to bool (true if not empty, false if empty). - inline operator bool() - { - return !this->empty(); - } + public /* functions: listeners */: - // Add new listener. + /** Add a new listener to the event. + * @param listener A listener bound with std::bind or a std::function. + */ + inline void add(std::function listener) + { + std::lock_guard lg(_lock); + if (_listeners.size() == 0) { + if (_cb_fill) { + _cb_fill(); + } + } + _listeners.push_back(listener); + } inline event<_args...>& operator+=(std::function listener) { this->add(listener); return *this; } - // Remove existing listener. + /** Remove an existing listener from the event. + * @param listener A listener bound with std::bind or a std::function. + */ + inline void remove(std::function listener) + { + std::lock_guard lg(_lock); + _listeners.remove(listener); + if (_listeners.size() == 0) { + if (_cb_clear) { + _cb_clear(); + } + } + } inline event<_args...>& operator-=(std::function listener) { this->remove(listener); return *this; } - public /* events */: + /** Check if there are any listeners for the event. + * @return bool `true` if there are none, otherwise `false`. + */ + inline bool empty() + { + std::lock_guard lg(_lock); + return _listeners.empty(); + } + inline operator bool() + { + return !this->empty(); + } + + /** Clear the list of listeners for the event. + */ + inline void clear() + { + std::lock_guard lg(_lock); + _listeners.clear(); + if (_cb_clear) { + _cb_clear(); + } + } + inline event<_args...>& operator=(nullptr_t) + { + clear(); + return *this; + } + + public /* callbacks */: + void set_listen_callback(std::function cb) { - std::lock_guard lock; - this->listen_cb = cb; + std::lock_guard lg(_lock); + this->_cb_fill = cb; } void set_silence_callback(std::function cb) { - std::lock_guard lock; - this->silence_cb = cb; + std::lock_guard lg(_lock); + this->_cb_clear = cb; } }; } // namespace util