]> git.stg.codes - stg.git/blobdiff - include/stg/subscriptions.h
Complete replacement notifiers with subscriptions.
[stg.git] / include / stg / subscriptions.h
index 1486e62d9003d1086edee1a0c25e3963513eb186..9ee9c64a6c3c8d2af9c989d9069dfa7a6bd389b7 100644 (file)
@@ -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<void ()>& f) noexcept : m_disconnect(f) {}
+        void disconnect() noexcept
+        {
+            if (!m_disconnect)
+                return;
+            m_disconnect();
+            m_disconnect = {};
+        }
+    private:
+        std::function<void ()> 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 <typename... Ts>
 class Subscriptions
 {
     public:
-        using Callback = std::function<void (Ts...)>;
+        using Callback = std::function<void (const Ts&...)>;
         using Callbacks = std::list<Callback>;
 
-        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 <typename F>
         Connection add(F&& f)
         {
             std::lock_guard lock(m_mutex);
-            return Connection(*this, m_callbacks.insert(m_callbacks.end(), Callback(std::forward<F>(f))));
+            return makeConn(m_callbacks.insert(m_callbacks.end(), Callback(std::forward<F>(f))));
         }
 
         template <typename C, typename... T2s>
         Connection add(C& c, void (C::*m)(T2s...))
         {
-            return add([&c, m](Ts&&... values){ (c.*m)(std::forward<Ts>(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)