/root/bitcoin/src/util/btcsignals.h
Line | Count | Source |
1 | | // Copyright (c) The Bitcoin Core developers |
2 | | // Distributed under the MIT software license, see the accompanying |
3 | | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
4 | | |
5 | | #ifndef BITCOIN_UTIL_BTCSIGNALS_H |
6 | | #define BITCOIN_UTIL_BTCSIGNALS_H |
7 | | |
8 | | #include <sync.h> |
9 | | |
10 | | #include <algorithm> |
11 | | #include <atomic> |
12 | | #include <functional> |
13 | | #include <memory> |
14 | | #include <optional> |
15 | | #include <type_traits> |
16 | | #include <utility> |
17 | | #include <vector> |
18 | | |
19 | | /** |
20 | | * btcsignals is a simple mechanism for signaling events to multiple subscribers. |
21 | | * It is api-compatible with a minimal subset of boost::signals2. |
22 | | * |
23 | | * Rather than using a custom slot type, and the features/complexity that they |
24 | | * imply, std::function is used to store the callbacks. Lifetime management of |
25 | | * the callbacks is left up to the user. |
26 | | * |
27 | | * All usage is thread-safe except for interacting with a connection while |
28 | | * copying/moving it on another thread. |
29 | | */ |
30 | | |
31 | | namespace btcsignals { |
32 | | |
33 | | /// The default combiner, which only returns void. |
34 | | class null_value |
35 | | { |
36 | | public: |
37 | | using result_type = void; |
38 | | }; |
39 | | |
40 | | /// A combiner, which checks if at least one callback returned true. |
41 | | class any_of |
42 | | { |
43 | | public: |
44 | | // This is the only supported combiner with a non-void return type. As |
45 | | // such, its behavior is embedded into the signal functor. |
46 | | using result_type = bool; |
47 | | }; |
48 | | |
49 | | template <typename Signature, typename Combiner = null_value> |
50 | | class signal; |
51 | | |
52 | | /* |
53 | | * State object representing the liveness of a registered callback. |
54 | | * signal::connect() returns an enabled connection which can be held and |
55 | | * disabled in the future. |
56 | | */ |
57 | | class connection |
58 | | { |
59 | | template <typename Signature, typename Combiner> |
60 | | friend class signal; |
61 | | /** |
62 | | * Track liveness. Also serves as a tag for the constructor used by signal. |
63 | | */ |
64 | | class liveness |
65 | | { |
66 | | friend class connection; |
67 | | std::atomic_bool m_connected{true}; |
68 | | |
69 | 0 | void disconnect() { m_connected.store(false); } |
70 | | public: |
71 | 0 | bool connected() const { return m_connected.load(); } |
72 | | }; |
73 | | |
74 | | /** |
75 | | * connections have shared_ptr-like copy and move semantics. |
76 | | */ |
77 | | std::shared_ptr<liveness> m_state{}; |
78 | | |
79 | | /** |
80 | | * Only a signal can create an enabled connection. |
81 | | */ |
82 | 3 | explicit connection(std::shared_ptr<liveness>&& state) : m_state{std::move(state)}{} |
83 | | |
84 | | public: |
85 | | /** |
86 | | * The default constructor creates a connection with no associated signal |
87 | | */ |
88 | | constexpr connection() noexcept = default; |
89 | | |
90 | | /** |
91 | | * If a callback is associated with this connection, prevent it from being |
92 | | * called in the future. |
93 | | * |
94 | | * If a connection is disabled as part of a signal's callback function, it |
95 | | * will _not_ be executed in the current signal invocation. |
96 | | * |
97 | | * Note that disconnected callbacks are not removed from their owning |
98 | | * signals here. They are garbage collected in signal::connect(). |
99 | | */ |
100 | | void disconnect() |
101 | 0 | { |
102 | 0 | if (m_state) { Branch (102:13): [True: 0, False: 0]
|
103 | 0 | m_state->disconnect(); |
104 | 0 | } |
105 | 0 | } |
106 | | |
107 | | /** |
108 | | * Returns true if this connection was created by a signal and has not been |
109 | | * disabled. |
110 | | */ |
111 | | bool connected() const |
112 | 0 | { |
113 | 0 | return m_state && m_state->connected(); |
114 | 0 | } |
115 | | }; |
116 | | |
117 | | /* |
118 | | * RAII-style connection management |
119 | | */ |
120 | | class scoped_connection |
121 | | { |
122 | | connection m_conn; |
123 | | |
124 | | public: |
125 | 0 | explicit scoped_connection(connection rhs) noexcept : m_conn{std::move(rhs)} {} |
126 | | |
127 | | scoped_connection(scoped_connection&&) noexcept = default; |
128 | | |
129 | | /** |
130 | | * For simplicity, disable copy construction and copy/move assignment. |
131 | | */ |
132 | | scoped_connection& operator=(scoped_connection&&) = delete; |
133 | | scoped_connection& operator=(const scoped_connection&) = delete; |
134 | | scoped_connection(const scoped_connection&) = delete; |
135 | | |
136 | | void disconnect() |
137 | 0 | { |
138 | 0 | m_conn.disconnect(); |
139 | 0 | } |
140 | | |
141 | | ~scoped_connection() |
142 | 0 | { |
143 | 0 | disconnect(); |
144 | 0 | } |
145 | | }; |
146 | | |
147 | | /* |
148 | | * Functor for calling zero or more connected callbacks |
149 | | */ |
150 | | template <typename Signature, typename Combiner> |
151 | | class signal |
152 | | { |
153 | | using function_type = std::function<Signature>; |
154 | | |
155 | | /* |
156 | | * Helper struct for maintaining a callback and its associated connection liveness |
157 | | */ |
158 | | struct connection_holder : connection::liveness { |
159 | | template <typename Callable> |
160 | 3 | connection_holder(Callable&& callback) : m_callback{std::forward<Callable>(callback)} |
161 | 3 | { |
162 | 3 | } Unexecuted instantiation: wallet.cpp:_ZN10btcsignals6signalIFvvENS_10null_valueEE17connection_holderC2IZN6wallet7CWallet31ConnectScriptPubKeyManNotifiersEvE3$_0EEOT_ Unexecuted instantiation: wallet.cpp:_ZN10btcsignals6signalIFvPKN6wallet15ScriptPubKeyManElENS_10null_valueEE17connection_holderC2IZNS1_7CWallet31ConnectScriptPubKeyManNotifiersEvE3$_1EEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFvvENS_10null_valueEE17connection_holderC2IRSt8functionIS1_EEEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiENS_10null_valueEE17connection_holderC2IRSt8functionIS9_EEEOT_ Unexecuted instantiation: interfaces.cpp:_ZN10btcsignals6signalIFvPN6wallet7CWalletEENS_10null_valueEE17connection_holderC2IZNS1_12_GLOBAL__N_110WalletImpl19handleStatusChangedESt8functionIFvvEEEUlS3_E_EEOT_ Unexecuted instantiation: interfaces.cpp:_ZN10btcsignals6signalIFvRKSt7variantIJ14CNoDestination17PubKeyDestination6PKHash10ScriptHash19WitnessV0ScriptHash16WitnessV0KeyHash16WitnessV1Taproot11PayToAnchor14WitnessUnknownEERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbN6wallet14AddressPurposeE10ChangeTypeENS_10null_valueEE17connection_holderC2IZNSM_12_GLOBAL__N_110WalletImpl24handleAddressBookChangedESt8functionISP_EEUlSD_SL_bSN_SO_E_EEOT_ Unexecuted instantiation: interfaces.cpp:_ZN10btcsignals6signalIFvRK22transaction_identifierILb0EE10ChangeTypeENS_10null_valueEE17connection_holderC2IZN6wallet12_GLOBAL__N_110WalletImpl24handleTransactionChangedESt8functionIS6_EEUlS4_S5_E_EEOT_ _ZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENS_10null_valueEE17connection_holderC2IRS9_EEOT_ Line | Count | Source | 160 | 1 | connection_holder(Callable&& callback) : m_callback{std::forward<Callable>(callback)} | 161 | 1 | { | 162 | 1 | } |
Unexecuted instantiation: init.cpp:_ZN10btcsignals6signalIFv20SynchronizationStateRK11CBlockIndexdENS_10null_valueEE17connection_holderC2IZ11AppInitMainRN4node11NodeContextEPN10interfaces21BlockAndHeaderTipInfoEE3$_9EEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENS_10null_valueEE17connection_holderC2IRSt8functionIS9_EEEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFvRK13bilingual_strjENS_10null_valueEE17connection_holderC2IRSt8functionIS4_EEEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFbRK13bilingual_strRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEjENS_6any_ofEE17connection_holderC2IRSt8functionISC_EEEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEibENS_10null_valueEE17connection_holderC2IRSt8functionIS9_EEEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFviENS_10null_valueEE17connection_holderC2IRSt8functionIS1_EEEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFvbENS_10null_valueEE17connection_holderC2IRSt8functionIS1_EEEOT_ Unexecuted instantiation: interfaces.cpp:_ZN10btcsignals6signalIFv20SynchronizationStateRK11CBlockIndexdENS_10null_valueEE17connection_holderC2IZN4node12_GLOBAL__N_18NodeImpl20handleNotifyBlockTipESt8functionIFvS1_N10interfaces8BlockTipEdEEEUlS1_S4_dE_EEOT_ Unexecuted instantiation: interfaces.cpp:_ZN10btcsignals6signalIFv20SynchronizationStatellbENS_10null_valueEE17connection_holderC2IZN4node12_GLOBAL__N_18NodeImpl21handleNotifyHeaderTipESt8functionIFvS1_N10interfaces8BlockTipEbEEEUlS1_llbE_EEOT_ _ZN10btcsignals6signalIFvRK13bilingual_strjENS_10null_valueEE17connection_holderC2IRS4_EEOT_ Line | Count | Source | 160 | 1 | connection_holder(Callable&& callback) : m_callback{std::forward<Callable>(callback)} | 161 | 1 | { | 162 | 1 | } |
_ZN10btcsignals6signalIFbRK13bilingual_strRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEjENS_6any_ofEE17connection_holderC2IRSC_EEOT_ Line | Count | Source | 160 | 1 | connection_holder(Callable&& callback) : m_callback{std::forward<Callable>(callback)} | 161 | 1 | { | 162 | 1 | } |
|
163 | | |
164 | | const function_type m_callback; |
165 | | }; |
166 | | |
167 | | mutable Mutex m_mutex; |
168 | | |
169 | | std::vector<std::shared_ptr<connection_holder>> m_connections GUARDED_BY(m_mutex){}; |
170 | | |
171 | | public: |
172 | | using result_type = Combiner::result_type; |
173 | | |
174 | 117k | constexpr signal() noexcept = default; _ZN10btcsignals6signalIFvvENS_10null_valueEEC2Ev Line | Count | Source | 174 | 49.1k | constexpr signal() noexcept = default; |
_ZN10btcsignals6signalIFvRKSt7variantIJ14CNoDestination17PubKeyDestination6PKHash10ScriptHash19WitnessV0ScriptHash16WitnessV0KeyHash16WitnessV1Taproot11PayToAnchor14WitnessUnknownEERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbN6wallet14AddressPurposeE10ChangeTypeENS_10null_valueEEC2Ev Line | Count | Source | 174 | 9.68k | constexpr signal() noexcept = default; |
_ZN10btcsignals6signalIFvRK22transaction_identifierILb0EE10ChangeTypeENS_10null_valueEEC2Ev Line | Count | Source | 174 | 9.68k | constexpr signal() noexcept = default; |
_ZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiENS_10null_valueEEC2Ev Line | Count | Source | 174 | 9.68k | constexpr signal() noexcept = default; |
_ZN10btcsignals6signalIFvPN6wallet7CWalletEENS_10null_valueEEC2Ev Line | Count | Source | 174 | 9.68k | constexpr signal() noexcept = default; |
_ZN10btcsignals6signalIFvPKN6wallet15ScriptPubKeyManElENS_10null_valueEEC2Ev Line | Count | Source | 174 | 29.8k | constexpr signal() noexcept = default; |
|
175 | 117k | ~signal() = default; _ZN10btcsignals6signalIFvPN6wallet7CWalletEENS_10null_valueEED2Ev Line | Count | Source | 175 | 9.68k | ~signal() = default; |
_ZN10btcsignals6signalIFvvENS_10null_valueEED2Ev Line | Count | Source | 175 | 49.1k | ~signal() = default; |
_ZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiENS_10null_valueEED2Ev Line | Count | Source | 175 | 9.68k | ~signal() = default; |
_ZN10btcsignals6signalIFvRK22transaction_identifierILb0EE10ChangeTypeENS_10null_valueEED2Ev Line | Count | Source | 175 | 9.68k | ~signal() = default; |
_ZN10btcsignals6signalIFvRKSt7variantIJ14CNoDestination17PubKeyDestination6PKHash10ScriptHash19WitnessV0ScriptHash16WitnessV0KeyHash16WitnessV1Taproot11PayToAnchor14WitnessUnknownEERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbN6wallet14AddressPurposeE10ChangeTypeENS_10null_valueEED2Ev Line | Count | Source | 175 | 9.68k | ~signal() = default; |
_ZN10btcsignals6signalIFvPKN6wallet15ScriptPubKeyManElENS_10null_valueEED2Ev Line | Count | Source | 175 | 29.8k | ~signal() = default; |
Unexecuted instantiation: _ZN10btcsignals6signalIFv20SynchronizationStatellbENS_10null_valueEED2Ev Unexecuted instantiation: _ZN10btcsignals6signalIFv20SynchronizationStateRK11CBlockIndexdENS_10null_valueEED2Ev Unexecuted instantiation: _ZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEibENS_10null_valueEED2Ev Unexecuted instantiation: _ZN10btcsignals6signalIFvbENS_10null_valueEED2Ev Unexecuted instantiation: _ZN10btcsignals6signalIFviENS_10null_valueEED2Ev Unexecuted instantiation: _ZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENS_10null_valueEED2Ev Unexecuted instantiation: _ZN10btcsignals6signalIFbRK13bilingual_strRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEjENS_6any_ofEED2Ev Unexecuted instantiation: _ZN10btcsignals6signalIFvRK13bilingual_strjENS_10null_valueEED2Ev |
176 | | |
177 | | /* |
178 | | * For simplicity, disable all moving/copying/assigning. |
179 | | */ |
180 | | signal(const signal&) = delete; |
181 | | signal(signal&&) = delete; |
182 | | signal& operator=(const signal&) = delete; |
183 | | signal& operator=(signal&&) = delete; |
184 | | |
185 | | /* |
186 | | * Execute all enabled callbacks for the signal. Rather than allowing for |
187 | | * custom combiners, the behavior of any_of is hard-coded here. |
188 | | * |
189 | | * Callbacks which return void require special handling. |
190 | | * |
191 | | * In order to avoid locking during the callbacks, the list of callbacks is |
192 | | * cached before they are called. This allows a callback to call connect(), |
193 | | * but the newly connected callback will not be run during the current |
194 | | * signal invocation. |
195 | | * |
196 | | * Note that the parameters are accepted as universal references, though |
197 | | * they are not perfectly forwarded as that could cause a use-after-move if |
198 | | * more than one callback is enabled. |
199 | | */ |
200 | | template <typename... Args> |
201 | | [[nodiscard]] result_type operator()(Args&&... args) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex) |
202 | 981k | { |
203 | 981k | std::vector<std::shared_ptr<connection_holder>> connections; |
204 | 981k | { |
205 | 981k | LOCK(m_mutex); |
206 | 981k | connections = m_connections; |
207 | 981k | } |
208 | 981k | if constexpr (std::is_void_v<result_type>) { |
209 | 981k | static_assert(std::is_same_v<result_type, typename function_type::result_type>, |
210 | 981k | "Callback result type must be equal to the combiner result type (void)."); |
211 | 981k | for (const auto& connection : connections) { Branch (211:41): [True: 0, False: 12.6k]
Branch (211:41): [True: 0, False: 64]
Branch (211:41): [True: 0, False: 0]
Branch (211:41): [True: 0, False: 0]
Branch (211:41): [True: 0, False: 0]
Branch (211:41): [True: 0, False: 0]
Branch (211:41): [True: 0, False: 0]
Branch (211:41): [True: 0, False: 165k]
Branch (211:41): [True: 0, False: 0]
Branch (211:41): [True: 0, False: 0]
Branch (211:41): [True: 0, False: 0]
Branch (211:41): [True: 0, False: 0]
Branch (211:41): [True: 0, False: 0]
Branch (211:41): [True: 0, False: 0]
Branch (211:41): [True: 0, False: 0]
Branch (211:41): [True: 0, False: 0]
Branch (211:41): [True: 0, False: 0]
Branch (211:41): [True: 0, False: 6]
Branch (211:41): [True: 0, False: 344k]
Branch (211:41): [True: 0, False: 458k]
|
212 | 0 | if (connection->connected()) { Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
Branch (212:21): [True: 0, False: 0]
|
213 | 0 | connection->m_callback(args...); |
214 | 0 | } |
215 | 0 | } |
216 | 981k | } else { |
217 | 0 | static_assert(std::is_same_v<Combiner, any_of>, |
218 | 0 | "only the any_of combiner is supported and hard-coded into this functor."); |
219 | 0 | static_assert(std::is_same_v<result_type, typename function_type::result_type>, |
220 | 0 | "Callback result type must be equal to the combiner result type (bool)."); |
221 | 0 | result_type ret{false}; |
222 | 0 | for (const auto& connection : connections) { Branch (222:41): [True: 0, False: 0]
|
223 | 0 | if (connection->connected()) { Branch (223:21): [True: 0, False: 0]
|
224 | 0 | ret |= connection->m_callback(args...); |
225 | 0 | } |
226 | 0 | } |
227 | 0 | return ret; |
228 | 0 | } |
229 | 981k | } _ZNK10btcsignals6signalIFvvENS_10null_valueEEclIJEEEvDpOT_ Line | Count | Source | 202 | 12.6k | { | 203 | 12.6k | std::vector<std::shared_ptr<connection_holder>> connections; | 204 | 12.6k | { | 205 | 12.6k | LOCK(m_mutex); | 206 | 12.6k | connections = m_connections; | 207 | 12.6k | } | 208 | 12.6k | if constexpr (std::is_void_v<result_type>) { | 209 | 12.6k | static_assert(std::is_same_v<result_type, typename function_type::result_type>, | 210 | 12.6k | "Callback result type must be equal to the combiner result type (void)."); | 211 | 12.6k | for (const auto& connection : connections) { Branch (211:41): [True: 0, False: 12.6k]
| 212 | 0 | if (connection->connected()) { Branch (212:21): [True: 0, False: 0]
| 213 | 0 | connection->m_callback(args...); | 214 | 0 | } | 215 | 0 | } | 216 | | } else { | 217 | | static_assert(std::is_same_v<Combiner, any_of>, | 218 | | "only the any_of combiner is supported and hard-coded into this functor."); | 219 | | static_assert(std::is_same_v<result_type, typename function_type::result_type>, | 220 | | "Callback result type must be equal to the combiner result type (bool)."); | 221 | | result_type ret{false}; | 222 | | for (const auto& connection : connections) { | 223 | | if (connection->connected()) { | 224 | | ret |= connection->m_callback(args...); | 225 | | } | 226 | | } | 227 | | return ret; | 228 | | } | 229 | 12.6k | } |
_ZNK10btcsignals6signalIFvPKN6wallet15ScriptPubKeyManElENS_10null_valueEEclIJPNS1_25DescriptorScriptPubKeyManERmEEEvDpOT_ Line | Count | Source | 202 | 64 | { | 203 | 64 | std::vector<std::shared_ptr<connection_holder>> connections; | 204 | 64 | { | 205 | 64 | LOCK(m_mutex); | 206 | 64 | connections = m_connections; | 207 | 64 | } | 208 | 64 | if constexpr (std::is_void_v<result_type>) { | 209 | 64 | static_assert(std::is_same_v<result_type, typename function_type::result_type>, | 210 | 64 | "Callback result type must be equal to the combiner result type (void)."); | 211 | 64 | for (const auto& connection : connections) { Branch (211:41): [True: 0, False: 64]
| 212 | 0 | if (connection->connected()) { Branch (212:21): [True: 0, False: 0]
| 213 | 0 | connection->m_callback(args...); | 214 | 0 | } | 215 | 0 | } | 216 | | } else { | 217 | | static_assert(std::is_same_v<Combiner, any_of>, | 218 | | "only the any_of combiner is supported and hard-coded into this functor."); | 219 | | static_assert(std::is_same_v<result_type, typename function_type::result_type>, | 220 | | "Callback result type must be equal to the combiner result type (bool)."); | 221 | | result_type ret{false}; | 222 | | for (const auto& connection : connections) { | 223 | | if (connection->connected()) { | 224 | | ret |= connection->m_callback(args...); | 225 | | } | 226 | | } | 227 | | return ret; | 228 | | } | 229 | 64 | } |
Unexecuted instantiation: _ZNK10btcsignals6signalIFvPN6wallet7CWalletEENS_10null_valueEEclIJS3_EEEvDpOT_ Unexecuted instantiation: _ZNK10btcsignals6signalIFvRK22transaction_identifierILb0EE10ChangeTypeENS_10null_valueEEclIJS4_S5_EEEvDpOT_ Unexecuted instantiation: _ZNK10btcsignals6signalIFvRK22transaction_identifierILb0EE10ChangeTypeENS_10null_valueEEclIJRS2_S5_EEEvDpOT_ Unexecuted instantiation: _ZNK10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiENS_10null_valueEEclIJS6_iEEEvDpOT_ Unexecuted instantiation: _ZNK10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiENS_10null_valueEEclIJS6_RKiEEEvDpOT_ _ZNK10btcsignals6signalIFvRKSt7variantIJ14CNoDestination17PubKeyDestination6PKHash10ScriptHash19WitnessV0ScriptHash16WitnessV0KeyHash16WitnessV1Taproot11PayToAnchor14WitnessUnknownEERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbN6wallet14AddressPurposeE10ChangeTypeENS_10null_valueEEclIJSD_SL_RbSN_SO_EEEvDpOT_ Line | Count | Source | 202 | 165k | { | 203 | 165k | std::vector<std::shared_ptr<connection_holder>> connections; | 204 | 165k | { | 205 | 165k | LOCK(m_mutex); | 206 | 165k | connections = m_connections; | 207 | 165k | } | 208 | 165k | if constexpr (std::is_void_v<result_type>) { | 209 | 165k | static_assert(std::is_same_v<result_type, typename function_type::result_type>, | 210 | 165k | "Callback result type must be equal to the combiner result type (void)."); | 211 | 165k | for (const auto& connection : connections) { Branch (211:41): [True: 0, False: 165k]
| 212 | 0 | if (connection->connected()) { Branch (212:21): [True: 0, False: 0]
| 213 | 0 | connection->m_callback(args...); | 214 | 0 | } | 215 | 0 | } | 216 | | } else { | 217 | | static_assert(std::is_same_v<Combiner, any_of>, | 218 | | "only the any_of combiner is supported and hard-coded into this functor."); | 219 | | static_assert(std::is_same_v<result_type, typename function_type::result_type>, | 220 | | "Callback result type must be equal to the combiner result type (bool)."); | 221 | | result_type ret{false}; | 222 | | for (const auto& connection : connections) { | 223 | | if (connection->connected()) { | 224 | | ret |= connection->m_callback(args...); | 225 | | } | 226 | | } | 227 | | return ret; | 228 | | } | 229 | 165k | } |
Unexecuted instantiation: _ZNK10btcsignals6signalIFvRKSt7variantIJ14CNoDestination17PubKeyDestination6PKHash10ScriptHash19WitnessV0ScriptHash16WitnessV0KeyHash16WitnessV1Taproot11PayToAnchor14WitnessUnknownEERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbN6wallet14AddressPurposeE10ChangeTypeENS_10null_valueEEclIJSD_RA1_KcbSN_SO_EEEvDpOT_ Unexecuted instantiation: _ZNK10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENS_10null_valueEEclIJN4util17TranslatedLiteralEEEEvDpOT_ Unexecuted instantiation: _ZNK10btcsignals6signalIFvRK13bilingual_strjENS_10null_valueEEclIJS1_N18CClientUIInterface15MessageBoxFlagsEEEEvDpOT_ Unexecuted instantiation: _ZNK10btcsignals6signalIFvRK13bilingual_strjENS_10null_valueEEclIJN4util17TranslatedLiteralEN18CClientUIInterface15MessageBoxFlagsEEEEvDpOT_ Unexecuted instantiation: _ZNK10btcsignals6signalIFbRK13bilingual_strRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEjENS_6any_ofEEclIJS1_S9_jEEEbDpOT_ Unexecuted instantiation: _ZNK10btcsignals6signalIFviENS_10null_valueEEclIJRmEEEvDpOT_ Unexecuted instantiation: _ZNK10btcsignals6signalIFvbENS_10null_valueEEclIJRSt6atomicIbEEEEvDpOT_ Unexecuted instantiation: _ZNK10btcsignals6signalIFvRK13bilingual_strjENS_10null_valueEEclIJRS1_N18CClientUIInterface15MessageBoxFlagsEEEEvDpOT_ Unexecuted instantiation: _ZNK10btcsignals6signalIFvRK13bilingual_strjENS_10null_valueEEclIJS3_N18CClientUIInterface15MessageBoxFlagsEEEEvDpOT_ Unexecuted instantiation: _ZNK10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENS_10null_valueEEclIJS8_EEEvDpOT_ _ZNK10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEibENS_10null_valueEEclIJS8_RiRbEEEvDpOT_ Line | Count | Source | 202 | 6 | { | 203 | 6 | std::vector<std::shared_ptr<connection_holder>> connections; | 204 | 6 | { | 205 | 6 | LOCK(m_mutex); | 206 | 6 | connections = m_connections; | 207 | 6 | } | 208 | 6 | if constexpr (std::is_void_v<result_type>) { | 209 | 6 | static_assert(std::is_same_v<result_type, typename function_type::result_type>, | 210 | 6 | "Callback result type must be equal to the combiner result type (void)."); | 211 | 6 | for (const auto& connection : connections) { Branch (211:41): [True: 0, False: 6]
| 212 | 0 | if (connection->connected()) { Branch (212:21): [True: 0, False: 0]
| 213 | 0 | connection->m_callback(args...); | 214 | 0 | } | 215 | 0 | } | 216 | | } else { | 217 | | static_assert(std::is_same_v<Combiner, any_of>, | 218 | | "only the any_of combiner is supported and hard-coded into this functor."); | 219 | | static_assert(std::is_same_v<result_type, typename function_type::result_type>, | 220 | | "Callback result type must be equal to the combiner result type (bool)."); | 221 | | result_type ret{false}; | 222 | | for (const auto& connection : connections) { | 223 | | if (connection->connected()) { | 224 | | ret |= connection->m_callback(args...); | 225 | | } | 226 | | } | 227 | | return ret; | 228 | | } | 229 | 6 | } |
_ZNK10btcsignals6signalIFv20SynchronizationStateRK11CBlockIndexdENS_10null_valueEEclIJRS1_S4_RdEEEvDpOT_ Line | Count | Source | 202 | 344k | { | 203 | 344k | std::vector<std::shared_ptr<connection_holder>> connections; | 204 | 344k | { | 205 | 344k | LOCK(m_mutex); | 206 | 344k | connections = m_connections; | 207 | 344k | } | 208 | 344k | if constexpr (std::is_void_v<result_type>) { | 209 | 344k | static_assert(std::is_same_v<result_type, typename function_type::result_type>, | 210 | 344k | "Callback result type must be equal to the combiner result type (void)."); | 211 | 344k | for (const auto& connection : connections) { Branch (211:41): [True: 0, False: 344k]
| 212 | 0 | if (connection->connected()) { Branch (212:21): [True: 0, False: 0]
| 213 | 0 | connection->m_callback(args...); | 214 | 0 | } | 215 | 0 | } | 216 | | } else { | 217 | | static_assert(std::is_same_v<Combiner, any_of>, | 218 | | "only the any_of combiner is supported and hard-coded into this functor."); | 219 | | static_assert(std::is_same_v<result_type, typename function_type::result_type>, | 220 | | "Callback result type must be equal to the combiner result type (bool)."); | 221 | | result_type ret{false}; | 222 | | for (const auto& connection : connections) { | 223 | | if (connection->connected()) { | 224 | | ret |= connection->m_callback(args...); | 225 | | } | 226 | | } | 227 | | return ret; | 228 | | } | 229 | 344k | } |
_ZNK10btcsignals6signalIFv20SynchronizationStatellbENS_10null_valueEEclIJRS1_RlS7_RbEEEvDpOT_ Line | Count | Source | 202 | 458k | { | 203 | 458k | std::vector<std::shared_ptr<connection_holder>> connections; | 204 | 458k | { | 205 | 458k | LOCK(m_mutex); | 206 | 458k | connections = m_connections; | 207 | 458k | } | 208 | 458k | if constexpr (std::is_void_v<result_type>) { | 209 | 458k | static_assert(std::is_same_v<result_type, typename function_type::result_type>, | 210 | 458k | "Callback result type must be equal to the combiner result type (void)."); | 211 | 458k | for (const auto& connection : connections) { Branch (211:41): [True: 0, False: 458k]
| 212 | 0 | if (connection->connected()) { Branch (212:21): [True: 0, False: 0]
| 213 | 0 | connection->m_callback(args...); | 214 | 0 | } | 215 | 0 | } | 216 | | } else { | 217 | | static_assert(std::is_same_v<Combiner, any_of>, | 218 | | "only the any_of combiner is supported and hard-coded into this functor."); | 219 | | static_assert(std::is_same_v<result_type, typename function_type::result_type>, | 220 | | "Callback result type must be equal to the combiner result type (bool)."); | 221 | | result_type ret{false}; | 222 | | for (const auto& connection : connections) { | 223 | | if (connection->connected()) { | 224 | | ret |= connection->m_callback(args...); | 225 | | } | 226 | | } | 227 | | return ret; | 228 | | } | 229 | 458k | } |
|
230 | | |
231 | | /* |
232 | | * Connect a new callback to the signal. A forwarding callable accepts |
233 | | * anything that can be stored in a std::function. |
234 | | */ |
235 | | template <typename Callable> |
236 | | connection connect(Callable&& func) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex) |
237 | 3 | { |
238 | 3 | LOCK(m_mutex); |
239 | | |
240 | | // Garbage-collect disconnected connections to prevent unbounded growth |
241 | 3 | std::erase_if(m_connections, [](const auto& holder) { return !holder->connected(); });Unexecuted instantiation: wallet.cpp:_ZZN10btcsignals6signalIFvvENS_10null_valueEE7connectIZN6wallet7CWallet31ConnectScriptPubKeyManNotifiersEvE3$_0EENS_10connectionEOT_ENKUlRKS9_E_clISt10shared_ptrINS3_17connection_holderEEEEDaSC_ Unexecuted instantiation: wallet.cpp:_ZZN10btcsignals6signalIFvPKN6wallet15ScriptPubKeyManElENS_10null_valueEE7connectIZNS1_7CWallet31ConnectScriptPubKeyManNotifiersEvE3$_1EENS_10connectionEOT_ENKUlRKSC_E_clISt10shared_ptrINS7_17connection_holderEEEEDaSF_ Unexecuted instantiation: _ZZN10btcsignals6signalIFvvENS_10null_valueEE7connectIRSt8functionIS1_EEENS_10connectionEOT_ENKUlRKS9_E_clISt10shared_ptrINS3_17connection_holderEEEEDaSC_ Unexecuted instantiation: _ZZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiENS_10null_valueEE7connectIRSt8functionIS9_EEENS_10connectionEOT_ENKUlRKSH_E_clISt10shared_ptrINSB_17connection_holderEEEEDaSK_ Unexecuted instantiation: interfaces.cpp:_ZZN10btcsignals6signalIFvPN6wallet7CWalletEENS_10null_valueEE7connectIZNS1_12_GLOBAL__N_110WalletImpl19handleStatusChangedESt8functionIFvvEEEUlS3_E_EENS_10connectionEOT_ENKUlRKSF_E_clISt10shared_ptrINS6_17connection_holderEEEEDaSI_ Unexecuted instantiation: interfaces.cpp:_ZZN10btcsignals6signalIFvRKSt7variantIJ14CNoDestination17PubKeyDestination6PKHash10ScriptHash19WitnessV0ScriptHash16WitnessV0KeyHash16WitnessV1Taproot11PayToAnchor14WitnessUnknownEERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbN6wallet14AddressPurposeE10ChangeTypeENS_10null_valueEE7connectIZNSM_12_GLOBAL__N_110WalletImpl24handleAddressBookChangedESt8functionISP_EEUlSD_SL_bSN_SO_E_EENS_10connectionEOT_ENKUlRKSZ_E_clISt10shared_ptrINSR_17connection_holderEEEEDaS12_ Unexecuted instantiation: interfaces.cpp:_ZZN10btcsignals6signalIFvRK22transaction_identifierILb0EE10ChangeTypeENS_10null_valueEE7connectIZN6wallet12_GLOBAL__N_110WalletImpl24handleTransactionChangedESt8functionIS6_EEUlS4_S5_E_EENS_10connectionEOT_ENKUlRKSH_E_clISt10shared_ptrINS8_17connection_holderEEEEDaSK_ Unexecuted instantiation: _ZZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENS_10null_valueEE7connectIRS9_EENS_10connectionEOT_ENKUlRKSF_E_clISt10shared_ptrINSB_17connection_holderEEEEDaSI_ Unexecuted instantiation: init.cpp:_ZZN10btcsignals6signalIFv20SynchronizationStateRK11CBlockIndexdENS_10null_valueEE7connectIZ11AppInitMainRN4node11NodeContextEPN10interfaces21BlockAndHeaderTipInfoEE3$_9EENS_10connectionEOT_ENKUlRKSH_E_clISt10shared_ptrINS7_17connection_holderEEEEDaSK_ Unexecuted instantiation: _ZZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENS_10null_valueEE7connectIRSt8functionIS9_EEENS_10connectionEOT_ENKUlRKSH_E_clISt10shared_ptrINSB_17connection_holderEEEEDaSK_ Unexecuted instantiation: _ZZN10btcsignals6signalIFvRK13bilingual_strjENS_10null_valueEE7connectIRSt8functionIS4_EEENS_10connectionEOT_ENKUlRKSC_E_clISt10shared_ptrINS6_17connection_holderEEEEDaSF_ Unexecuted instantiation: _ZZN10btcsignals6signalIFbRK13bilingual_strRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEjENS_6any_ofEE7connectIRSt8functionISC_EEENS_10connectionEOT_ENKUlRKSK_E_clISt10shared_ptrINSE_17connection_holderEEEEDaSN_ Unexecuted instantiation: _ZZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEibENS_10null_valueEE7connectIRSt8functionIS9_EEENS_10connectionEOT_ENKUlRKSH_E_clISt10shared_ptrINSB_17connection_holderEEEEDaSK_ Unexecuted instantiation: _ZZN10btcsignals6signalIFviENS_10null_valueEE7connectIRSt8functionIS1_EEENS_10connectionEOT_ENKUlRKS9_E_clISt10shared_ptrINS3_17connection_holderEEEEDaSC_ Unexecuted instantiation: _ZZN10btcsignals6signalIFvbENS_10null_valueEE7connectIRSt8functionIS1_EEENS_10connectionEOT_ENKUlRKS9_E_clISt10shared_ptrINS3_17connection_holderEEEEDaSC_ Unexecuted instantiation: interfaces.cpp:_ZZN10btcsignals6signalIFv20SynchronizationStateRK11CBlockIndexdENS_10null_valueEE7connectIZN4node12_GLOBAL__N_18NodeImpl20handleNotifyBlockTipESt8functionIFvS1_N10interfaces8BlockTipEdEEEUlS1_S4_dE_EENS_10connectionEOT_ENKUlRKSJ_E_clISt10shared_ptrINS7_17connection_holderEEEEDaSM_ Unexecuted instantiation: interfaces.cpp:_ZZN10btcsignals6signalIFv20SynchronizationStatellbENS_10null_valueEE7connectIZN4node12_GLOBAL__N_18NodeImpl21handleNotifyHeaderTipESt8functionIFvS1_N10interfaces8BlockTipEbEEEUlS1_llbE_EENS_10connectionEOT_ENKUlRKSG_E_clISt10shared_ptrINS4_17connection_holderEEEEDaSJ_ Unexecuted instantiation: _ZZN10btcsignals6signalIFvRK13bilingual_strjENS_10null_valueEE7connectIRS4_EENS_10connectionEOT_ENKUlRKSA_E_clISt10shared_ptrINS6_17connection_holderEEEEDaSD_ Unexecuted instantiation: _ZZN10btcsignals6signalIFbRK13bilingual_strRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEjENS_6any_ofEE7connectIRSC_EENS_10connectionEOT_ENKUlRKSI_E_clISt10shared_ptrINSE_17connection_holderEEEEDaSL_ |
242 | | |
243 | 3 | const auto& entry = m_connections.emplace_back(std::make_shared<connection_holder>(std::forward<Callable>(func))); |
244 | 3 | return connection(entry); |
245 | 3 | } Unexecuted instantiation: wallet.cpp:_ZN10btcsignals6signalIFvvENS_10null_valueEE7connectIZN6wallet7CWallet31ConnectScriptPubKeyManNotifiersEvE3$_0EENS_10connectionEOT_ Unexecuted instantiation: wallet.cpp:_ZN10btcsignals6signalIFvPKN6wallet15ScriptPubKeyManElENS_10null_valueEE7connectIZNS1_7CWallet31ConnectScriptPubKeyManNotifiersEvE3$_1EENS_10connectionEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFvvENS_10null_valueEE7connectIRSt8functionIS1_EEENS_10connectionEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiENS_10null_valueEE7connectIRSt8functionIS9_EEENS_10connectionEOT_ Unexecuted instantiation: interfaces.cpp:_ZN10btcsignals6signalIFvPN6wallet7CWalletEENS_10null_valueEE7connectIZNS1_12_GLOBAL__N_110WalletImpl19handleStatusChangedESt8functionIFvvEEEUlS3_E_EENS_10connectionEOT_ Unexecuted instantiation: interfaces.cpp:_ZN10btcsignals6signalIFvRKSt7variantIJ14CNoDestination17PubKeyDestination6PKHash10ScriptHash19WitnessV0ScriptHash16WitnessV0KeyHash16WitnessV1Taproot11PayToAnchor14WitnessUnknownEERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEbN6wallet14AddressPurposeE10ChangeTypeENS_10null_valueEE7connectIZNSM_12_GLOBAL__N_110WalletImpl24handleAddressBookChangedESt8functionISP_EEUlSD_SL_bSN_SO_E_EENS_10connectionEOT_ Unexecuted instantiation: interfaces.cpp:_ZN10btcsignals6signalIFvRK22transaction_identifierILb0EE10ChangeTypeENS_10null_valueEE7connectIZN6wallet12_GLOBAL__N_110WalletImpl24handleTransactionChangedESt8functionIS6_EEUlS4_S5_E_EENS_10connectionEOT_ _ZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENS_10null_valueEE7connectIRS9_EENS_10connectionEOT_ Line | Count | Source | 237 | 1 | { | 238 | 1 | LOCK(m_mutex); | 239 | | | 240 | | // Garbage-collect disconnected connections to prevent unbounded growth | 241 | 1 | std::erase_if(m_connections, [](const auto& holder) { return !holder->connected(); }); | 242 | | | 243 | 1 | const auto& entry = m_connections.emplace_back(std::make_shared<connection_holder>(std::forward<Callable>(func))); | 244 | 1 | return connection(entry); | 245 | 1 | } |
Unexecuted instantiation: init.cpp:_ZN10btcsignals6signalIFv20SynchronizationStateRK11CBlockIndexdENS_10null_valueEE7connectIZ11AppInitMainRN4node11NodeContextEPN10interfaces21BlockAndHeaderTipInfoEE3$_9EENS_10connectionEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEENS_10null_valueEE7connectIRSt8functionIS9_EEENS_10connectionEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFvRK13bilingual_strjENS_10null_valueEE7connectIRSt8functionIS4_EEENS_10connectionEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFbRK13bilingual_strRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEjENS_6any_ofEE7connectIRSt8functionISC_EEENS_10connectionEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFvRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEibENS_10null_valueEE7connectIRSt8functionIS9_EEENS_10connectionEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFviENS_10null_valueEE7connectIRSt8functionIS1_EEENS_10connectionEOT_ Unexecuted instantiation: _ZN10btcsignals6signalIFvbENS_10null_valueEE7connectIRSt8functionIS1_EEENS_10connectionEOT_ Unexecuted instantiation: interfaces.cpp:_ZN10btcsignals6signalIFv20SynchronizationStateRK11CBlockIndexdENS_10null_valueEE7connectIZN4node12_GLOBAL__N_18NodeImpl20handleNotifyBlockTipESt8functionIFvS1_N10interfaces8BlockTipEdEEEUlS1_S4_dE_EENS_10connectionEOT_ Unexecuted instantiation: interfaces.cpp:_ZN10btcsignals6signalIFv20SynchronizationStatellbENS_10null_valueEE7connectIZN4node12_GLOBAL__N_18NodeImpl21handleNotifyHeaderTipESt8functionIFvS1_N10interfaces8BlockTipEbEEEUlS1_llbE_EENS_10connectionEOT_ _ZN10btcsignals6signalIFvRK13bilingual_strjENS_10null_valueEE7connectIRS4_EENS_10connectionEOT_ Line | Count | Source | 237 | 1 | { | 238 | 1 | LOCK(m_mutex); | 239 | | | 240 | | // Garbage-collect disconnected connections to prevent unbounded growth | 241 | 1 | std::erase_if(m_connections, [](const auto& holder) { return !holder->connected(); }); | 242 | | | 243 | 1 | const auto& entry = m_connections.emplace_back(std::make_shared<connection_holder>(std::forward<Callable>(func))); | 244 | 1 | return connection(entry); | 245 | 1 | } |
_ZN10btcsignals6signalIFbRK13bilingual_strRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEjENS_6any_ofEE7connectIRSC_EENS_10connectionEOT_ Line | Count | Source | 237 | 1 | { | 238 | 1 | LOCK(m_mutex); | 239 | | | 240 | | // Garbage-collect disconnected connections to prevent unbounded growth | 241 | 1 | std::erase_if(m_connections, [](const auto& holder) { return !holder->connected(); }); | 242 | | | 243 | 1 | const auto& entry = m_connections.emplace_back(std::make_shared<connection_holder>(std::forward<Callable>(func))); | 244 | 1 | return connection(entry); | 245 | 1 | } |
|
246 | | |
247 | | /* |
248 | | * Returns true if there are no enabled callbacks |
249 | | */ |
250 | | [[nodiscard]] bool empty() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex) |
251 | 9.68k | { |
252 | 9.68k | LOCK(m_mutex); |
253 | 9.68k | return std::ranges::none_of(m_connections, [](const auto& holder) { |
254 | 0 | return holder->connected(); |
255 | 0 | }); |
256 | 9.68k | } |
257 | | }; |
258 | | |
259 | | } // namespace btcsignals |
260 | | |
261 | | #endif // BITCOIN_UTIL_BTCSIGNALS_H |