diff --git a/src/btcsignals.h b/src/btcsignals.h index f4c2530be91..ebe7a5acb78 100644 --- a/src/btcsignals.h +++ b/src/btcsignals.h @@ -56,23 +56,28 @@ class connection { template friend class signal; - - /* - * Tag for the constructor used by signal. + /** + * Track liveness. Also serves as a tag for the constructor used by signal. */ - struct enabled_tag_type { + class liveness + { + friend class connection; + std::atomic_bool m_connected{true}; + + void disconnect() { m_connected.store(false); } + public: + bool connected() const { return m_connected.load(); } }; - static constexpr enabled_tag_type enabled_tag{}; /** * connections have shared_ptr-like copy and move semantics. */ - std::shared_ptr m_connected{}; + std::shared_ptr m_state{}; /** * Only a signal can create an enabled connection. */ - explicit connection(enabled_tag_type /*unused*/) : m_connected{std::make_shared(true)} {} + explicit connection(std::shared_ptr&& state) : m_state{std::move(state)}{} public: /** @@ -92,8 +97,8 @@ public: */ void disconnect() { - if (m_connected) { - m_connected->store(false); + if (m_state) { + m_state->disconnect(); } } @@ -103,7 +108,7 @@ public: */ bool connected() const { - return m_connected && m_connected->load(); + return m_state && m_state->connected(); } }; @@ -148,23 +153,19 @@ class signal static_assert(std::is_same_v>, "only the optional_last_value combiner is supported"); /* - * Helper struct for maintaining a callback and its associated connection + * Helper struct for maintaining a callback and its associated connection liveness */ - struct connection_holder { + struct connection_holder : connection::liveness { template connection_holder(Callable&& callback) : m_callback{std::forward(callback)} { } - connection m_connection{connection::enabled_tag}; - function_type m_callback; + const function_type m_callback; }; mutable Mutex m_mutex; - /* Store connection_holders as shared_ptrs to avoid having to copy them by - * value in operator(). - */ std::vector> m_connections GUARDED_BY(m_mutex){}; public: @@ -208,14 +209,14 @@ public: } if constexpr (std::is_void_v) { for (const auto& connection : connections) { - if (connection->m_connection.connected()) { + if (connection->connected()) { connection->m_callback(args...); } } } else { result_type ret{std::nullopt}; for (const auto& connection : connections) { - if (connection->m_connection.connected()) { + if (connection->connected()) { ret.emplace(connection->m_callback(args...)); } } @@ -233,10 +234,10 @@ public: LOCK(m_mutex); // Garbage-collect disconnected connections to prevent unbounded growth - std::erase_if(m_connections, [](const auto& holder) { return !holder->m_connection.connected(); }); + std::erase_if(m_connections, [](const auto& holder) { return !holder->connected(); }); - const auto& connection = m_connections.emplace_back(std::make_shared(std::forward(func))); - return connection->m_connection; + const auto& entry = m_connections.emplace_back(std::make_shared(std::forward(func))); + return connection(entry); } /* @@ -246,7 +247,7 @@ public: { LOCK(m_mutex); return std::ranges::none_of(m_connections, [](const auto& holder) { - return holder->m_connection.connected(); + return holder->connected(); }); } };