#pragma once #include #include #include namespace STG { template class Subscriptions { public: using Callback = std::function; using Callbacks = std::list; class Connection { 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; }; template Connection add(F&& f) { std::lock_guard lock(m_mutex); return Connection(*this, 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)...); }); } void remove(typename Callbacks::iterator i) { std::lock_guard lock(m_mutex); m_callbacks.erase(i); } void notify(Ts&&... values) { std::lock_guard lock(m_mutex); for (auto& cb : m_callbacks) cb(values...); } bool empty() const noexcept { std::lock_guard lock(m_mutex); return m_callbacks.empty(); } size_t size() const noexcept { std::lock_guard lock(m_mutex); return m_callbacks.size(); } private: mutable std::mutex m_mutex; Callbacks m_callbacks; }; }