Skip to content

Commit 217c78b

Browse files
committed
Move event subscription from protocol_peer to protocol.
1 parent ad1efad commit 217c78b

File tree

4 files changed

+101
-84
lines changed

4 files changed

+101
-84
lines changed

include/bitcoin/node/protocols/protocol.hpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ namespace libbitcoin {
3131
namespace node {
3232

3333
/// Abstract base for node protocols, thread safe.
34+
/// This node::protocol is not derived from network::protocol, but given the
35+
/// channel constructor parameter is derived from network::channel, the strand
36+
/// is accessible despite lack of bind/post/parallel templates access. This
37+
/// allows event subscription by derived protocols without the need to derive
38+
/// from protocol_peer (which would prevent derivation from service protocols).
3439
class BCN_API protocol
3540
{
3641
protected:
@@ -42,8 +47,7 @@ class BCN_API protocol
4247
// reinterpret_pointer_cast because channel is abstract.
4348
inline protocol(const auto& session,
4449
const network::channel::ptr& channel) NOEXCEPT
45-
: channel_(std::reinterpret_pointer_cast<node::channel>(channel)),
46-
session_(session)
50+
: channel_(channel), session_(session)
4751
{
4852
}
4953

@@ -63,12 +67,35 @@ class BCN_API protocol
6367
/// The candidate|confirmed chain is current.
6468
virtual bool is_current(bool confirmed) const NOEXCEPT;
6569

70+
/// Events subscription.
71+
/// -----------------------------------------------------------------------
72+
73+
/// Subscribe to chaser events (max one active per protocol).
74+
virtual void subscribe_events(event_notifier&& handler) NOEXCEPT;
75+
76+
/// Override to handle subscription completion (stranded).
77+
virtual void subscribed(const code& ec, object_key key) NOEXCEPT;
78+
79+
/// Unsubscribe from chaser events.
80+
/// Subscribing protocol must invoke from overridden stopping().
81+
virtual void unsubscribe_events() NOEXCEPT;
82+
83+
/// Get the subscription key (for notify_one).
84+
virtual object_key events_key() const NOEXCEPT;
85+
6686
private:
87+
void handle_subscribed(const code& ec, object_key key) NOEXCEPT;
88+
void handle_subscribe(const code& ec, object_key key,
89+
const event_completer& complete) NOEXCEPT;
90+
6791
// This channel requires stranded calls, base is thread safe.
68-
const node::channel::ptr channel_;
92+
const network::channel::ptr channel_;
6993

7094
// This is thread safe.
7195
const node::session::ptr session_;
96+
97+
// This is protected by singular subscription.
98+
object_key key_{};
7299
};
73100

74101
} // namespace node

include/bitcoin/node/protocols/protocol_peer.hpp

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -102,35 +102,12 @@ class BCN_API protocol_peer
102102
virtual void notify_one(object_key key, const code& ec, chase event_,
103103
event_value value) const NOEXCEPT;
104104

105-
/// Events subscription.
106-
/// -----------------------------------------------------------------------
107-
108-
/// Subscribe to chaser events (max one active per protocol).
109-
virtual void subscribe_events(event_notifier&& handler) NOEXCEPT;
110-
111-
/// Override to handle subscription completion (stranded).
112-
virtual void subscribed(const code& ec, object_key key) NOEXCEPT;
113-
114-
/// Unsubscribe from chaser events.
115-
/// Subscribing protocol must invoke from overridden stopping().
116-
virtual void unsubscribe_events() NOEXCEPT;
117-
118-
/// Get the subscription key (for notify_one).
119-
virtual object_key events_key() const NOEXCEPT;
120-
121105
private:
122-
void handle_subscribed(const code& ec, object_key key) NOEXCEPT;
123-
void handle_subscribe(const code& ec, object_key key,
124-
const event_completer& complete) NOEXCEPT;
125-
126106
// This derived channel requires stranded calls, base is thread safe.
127107
const node::channel_peer::ptr channel_;
128108

129109
// This is thread safe.
130110
const node::session::ptr session_;
131-
132-
// This is protected by singular subscription.
133-
object_key key_{};
134111
};
135112

136113
} // namespace node

src/protocols/protocol.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
namespace libbitcoin {
2525
namespace node {
2626

27+
#define CLASS protocol
28+
29+
using namespace std::placeholders;
30+
2731
// Properties.
2832
// ----------------------------------------------------------------------------
2933

@@ -62,5 +66,71 @@ bool protocol::is_current(bool confirmed) const NOEXCEPT
6266
return session_->is_current(confirmed);
6367
}
6468

69+
// Events subscription.
70+
// ----------------------------------------------------------------------------
71+
72+
void protocol::subscribe_events(event_notifier&& handler) NOEXCEPT
73+
{
74+
// This is a shared instance multiply-derived from network::protocol.
75+
const auto self = dynamic_cast<network::protocol&>(*this)
76+
.shared_from_sibling<node::protocol, network::protocol>();
77+
78+
event_completer completer = std::bind(&protocol::handle_subscribed, self,
79+
_1, _2);
80+
81+
session_->subscribe_events(std::move(handler),
82+
std::bind(&protocol::handle_subscribe,
83+
self, _1, _2, std::move(completer)));
84+
}
85+
86+
// private
87+
void protocol::handle_subscribe(const code& ec, object_key key,
88+
const event_completer& complete) NOEXCEPT
89+
{
90+
// The key member is protected by one event subscription per protocol.
91+
BC_ASSERT_MSG(is_zero(key_), "unsafe access");
92+
93+
// Protocol stop is thread safe.
94+
if (ec)
95+
{
96+
channel_->stop(ec);
97+
return;
98+
}
99+
100+
key_ = key;
101+
complete(ec, key_);
102+
}
103+
104+
void protocol::handle_subscribed(const code& ec, object_key key) NOEXCEPT
105+
{
106+
// This is a shared instance multiply-derived from network::protocol.
107+
const auto self = dynamic_cast<network::protocol&>(*this)
108+
.shared_from_sibling<node::protocol, network::protocol>();
109+
110+
boost::asio::post(channel_->strand(),
111+
std::bind(&protocol::subscribed, self, ec, key));
112+
}
113+
114+
void protocol::subscribed(const code& ec, object_key) NOEXCEPT
115+
{
116+
BC_ASSERT(channel_->stranded());
117+
118+
// Unsubscriber race is ok.
119+
if (channel_->stopped() || ec)
120+
unsubscribe_events();
121+
}
122+
123+
// As this has no completion handler resubscription is not allowed.
124+
void protocol::unsubscribe_events() NOEXCEPT
125+
{
126+
session_->unsubscribe_events(key_);
127+
key_ = {};
128+
}
129+
130+
object_key protocol::events_key() const NOEXCEPT
131+
{
132+
return key_;
133+
}
134+
65135
} // namespace node
66136
} // namespace libbitcoin

src/protocols/protocol_peer.cpp

Lines changed: 1 addition & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,8 @@
2323
namespace libbitcoin {
2424
namespace node {
2525

26-
#define CLASS protocol_peer
27-
2826
using namespace system;
2927
using namespace network;
30-
using namespace std::placeholders;
3128

3229
// Organizers.
3330
// ----------------------------------------------------------------------------
@@ -62,7 +59,7 @@ void protocol_peer::performance(uint64_t speed,
6259
network::result_handler&& handler) const NOEXCEPT
6360
{
6461
// Passed protocol->session->full_node->check_chaser.post->do_update.
65-
session_->performance(key_, speed, std::move(handler));
62+
session_->performance(events_key(), speed, std::move(handler));
6663
}
6764

6865
code protocol_peer::fault(const code& ec) NOEXCEPT
@@ -103,59 +100,5 @@ void protocol_peer::notify_one(object_key key, const code& ec, chase event_,
103100
session_->notify_one(key, ec, event_, value);
104101
}
105102

106-
// Events subscription.
107-
// ----------------------------------------------------------------------------
108-
109-
void protocol_peer::subscribe_events(event_notifier&& handler) NOEXCEPT
110-
{
111-
event_completer completer = BIND(handle_subscribed, _1, _2);
112-
session_->subscribe_events(std::move(handler),
113-
BIND(handle_subscribe, _1, _2, std::move(completer)));
114-
}
115-
116-
// private
117-
void protocol_peer::handle_subscribe(const code& ec, object_key key,
118-
const event_completer& complete) NOEXCEPT
119-
{
120-
// The key member is protected by one event subscription per protocol.
121-
BC_ASSERT_MSG(is_zero(key_), "unsafe access");
122-
123-
// Protocol stop is thread safe.
124-
if (ec)
125-
{
126-
stop(ec);
127-
return;
128-
}
129-
130-
key_ = key;
131-
complete(ec, key_);
132-
}
133-
134-
void protocol_peer::handle_subscribed(const code& ec, object_key key) NOEXCEPT
135-
{
136-
POST(subscribed, ec, key);
137-
}
138-
139-
void protocol_peer::subscribed(const code& ec, object_key) NOEXCEPT
140-
{
141-
BC_ASSERT(stranded());
142-
143-
// Unsubscriber race is ok.
144-
if (stopped(ec))
145-
unsubscribe_events();
146-
}
147-
148-
// As this has no completion handler resubscription is not allowed.
149-
void protocol_peer::unsubscribe_events() NOEXCEPT
150-
{
151-
session_->unsubscribe_events(key_);
152-
key_ = {};
153-
}
154-
155-
object_key protocol_peer::events_key() const NOEXCEPT
156-
{
157-
return key_;
158-
}
159-
160103
} // namespace node
161104
} // namespace libbitcoin

0 commit comments

Comments
 (0)