Skip to content

Commit 242b0eb

Browse files
committed
btcsignals: use a single shared_ptr for liveness and callback
This simplifies the implementation and eliminates an unnecessary shared_ptr. Suggested by Marco Falke. <Co-authored-by: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz>
1 parent b12f43a commit 242b0eb

1 file changed

Lines changed: 24 additions & 23 deletions

File tree

src/btcsignals.h

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,28 @@ class connection
5656
{
5757
template <typename Signature, typename Combiner>
5858
friend class signal;
59-
60-
/*
61-
* Tag for the constructor used by signal.
59+
/**
60+
* Track liveness. Also serves as a tag for the constructor used by signal.
6261
*/
63-
struct enabled_tag_type {
62+
class liveness
63+
{
64+
friend class connection;
65+
std::atomic_bool m_connected{true};
66+
67+
void disconnect() { m_connected.store(false); }
68+
public:
69+
bool connected() const { return m_connected.load(); }
6470
};
65-
static constexpr enabled_tag_type enabled_tag{};
6671

6772
/**
6873
* connections have shared_ptr-like copy and move semantics.
6974
*/
70-
std::shared_ptr<std::atomic_bool> m_connected{};
75+
std::shared_ptr<liveness> m_state{};
7176

7277
/**
7378
* Only a signal can create an enabled connection.
7479
*/
75-
explicit connection(enabled_tag_type /*unused*/) : m_connected{std::make_shared<std::atomic_bool>(true)} {}
80+
explicit connection(std::shared_ptr<liveness>&& state) : m_state{std::move(state)}{}
7681

7782
public:
7883
/**
@@ -92,8 +97,8 @@ class connection
9297
*/
9398
void disconnect()
9499
{
95-
if (m_connected) {
96-
m_connected->store(false);
100+
if (m_state) {
101+
m_state->disconnect();
97102
}
98103
}
99104

@@ -103,7 +108,7 @@ class connection
103108
*/
104109
bool connected() const
105110
{
106-
return m_connected && m_connected->load();
111+
return m_state && m_state->connected();
107112
}
108113
};
109114

@@ -148,23 +153,19 @@ class signal
148153
static_assert(std::is_same_v<Combiner, optional_last_value<typename function_type::result_type>>, "only the optional_last_value combiner is supported");
149154

150155
/*
151-
* Helper struct for maintaining a callback and its associated connection
156+
* Helper struct for maintaining a callback and its associated connection liveness
152157
*/
153-
struct connection_holder {
158+
struct connection_holder : connection::liveness {
154159
template <typename Callable>
155160
connection_holder(Callable&& callback) : m_callback{std::forward<Callable>(callback)}
156161
{
157162
}
158163

159-
connection m_connection{connection::enabled_tag};
160-
function_type m_callback;
164+
const function_type m_callback;
161165
};
162166

163167
mutable Mutex m_mutex;
164168

165-
/* Store connection_holders as shared_ptrs to avoid having to copy them by
166-
* value in operator().
167-
*/
168169
std::vector<std::shared_ptr<connection_holder>> m_connections GUARDED_BY(m_mutex){};
169170

170171
public:
@@ -208,14 +209,14 @@ class signal
208209
}
209210
if constexpr (std::is_void_v<result_type>) {
210211
for (const auto& connection : connections) {
211-
if (connection->m_connection.connected()) {
212+
if (connection->connected()) {
212213
connection->m_callback(args...);
213214
}
214215
}
215216
} else {
216217
result_type ret{std::nullopt};
217218
for (const auto& connection : connections) {
218-
if (connection->m_connection.connected()) {
219+
if (connection->connected()) {
219220
ret.emplace(connection->m_callback(args...));
220221
}
221222
}
@@ -233,10 +234,10 @@ class signal
233234
LOCK(m_mutex);
234235

235236
// Garbage-collect disconnected connections to prevent unbounded growth
236-
std::erase_if(m_connections, [](const auto& holder) { return !holder->m_connection.connected(); });
237+
std::erase_if(m_connections, [](const auto& holder) { return !holder->connected(); });
237238

238-
const auto& connection = m_connections.emplace_back(std::make_shared<connection_holder>(std::forward<Callable>(func)));
239-
return connection->m_connection;
239+
const auto& entry = m_connections.emplace_back(std::make_shared<connection_holder>(std::forward<Callable>(func)));
240+
return connection(entry);
240241
}
241242

242243
/*
@@ -246,7 +247,7 @@ class signal
246247
{
247248
LOCK(m_mutex);
248249
return std::ranges::none_of(m_connections, [](const auto& holder) {
249-
return holder->m_connection.connected();
250+
return holder->connected();
250251
});
251252
}
252253
};

0 commit comments

Comments
 (0)