X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/1c529746ff07312e30e76fd933c628c658e3c77d..b2b89723a2427bba8290bd6967a1ab39cbb630be:/include/stg/subscriptions.h diff --git a/include/stg/subscriptions.h b/include/stg/subscriptions.h index 1486e62d..9ee9c64a 100644 --- a/include/stg/subscriptions.h +++ b/include/stg/subscriptions.h @@ -7,48 +7,70 @@ namespace STG { +class Connection +{ + public: + Connection() = default; + + Connection(const Connection&) = delete; + Connection& operator=(const Connection&) = delete; + Connection(Connection&&) = default; + Connection& operator=(Connection&&) = default; + + Connection(const std::function& f) noexcept : m_disconnect(f) {} + void disconnect() noexcept + { + if (!m_disconnect) + return; + m_disconnect(); + m_disconnect = {}; + } + private: + std::function m_disconnect; +}; + +class ScopedConnection +{ + public: + ScopedConnection() = default; + + ScopedConnection(const ScopedConnection&) = delete; + ScopedConnection& operator=(const ScopedConnection&) = delete; + ScopedConnection(ScopedConnection&&) = default; + ScopedConnection& operator=(ScopedConnection&&) = default; + + ScopedConnection(Connection c) noexcept : m_conn(std::move(c)) {} + ~ScopedConnection() { disconnect(); } + + void disconnect() noexcept { m_conn.disconnect(); } + + private: + Connection m_conn; +}; + template class Subscriptions { public: - using Callback = std::function; + using Callback = std::function; using Callbacks = std::list; - class Connection + Connection makeConn(typename Callbacks::iterator i) noexcept { - public: - Connection(Subscriptions& s, typename Callbacks::iterator i) noexcept - : m_subscriptions(s), m_iterator(i), m_connected(true) - {} - ~Connection() - { - disconnect(); - } - - void disconnect() noexcept - { - if (!m_connected) - return; - m_subscriptions.remove(m_iterator); - m_connected = false; - } - private: - Subscriptions& m_subscriptions; - typename Callbacks::iterator m_iterator; - bool m_connected; - }; + return Connection([this, i](){ remove(i); }); + } template Connection add(F&& f) { std::lock_guard lock(m_mutex); - return Connection(*this, m_callbacks.insert(m_callbacks.end(), Callback(std::forward(f)))); + return makeConn(m_callbacks.insert(m_callbacks.end(), Callback(std::forward(f)))); } template Connection add(C& c, void (C::*m)(T2s...)) { - return add([&c, m](Ts&&... values){ (c.*m)(std::forward(values)...); }); + return add([&c, m](const Ts&... values){ (c.*m)(values...); }); } void remove(typename Callbacks::iterator i) @@ -57,7 +79,7 @@ class Subscriptions m_callbacks.erase(i); } - void notify(Ts&&... values) + void notify(const Ts&... values) { std::lock_guard lock(m_mutex); for (auto& cb : m_callbacks)