Coverage Report

Created: 2026-09-01 13:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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