1515#include " socket_ops.hpp"
1616#include " reactor_op.hpp"
1717
18+ #include < boost/version.hpp>
19+ #include < boost/asio/dispatch.hpp>
20+ #include < boost/asio/executor_work_guard.hpp>
21+ #if BOOST_VERSION >= 107900
22+ #include < boost/asio/recycling_allocator.hpp>
23+ #include < boost/asio/bind_allocator.hpp>
24+ #endif
25+
1826#include < zmq.h>
1927
2028#include < iterator>
29+ #include < type_traits>
2130
2231namespace azmq {
2332namespace detail {
@@ -30,6 +39,23 @@ class receive_buffer_op_base : public reactor_op {
3039 { }
3140
3241 virtual bool do_perform (socket_type& socket) override {
42+ return do_perform_impl (socket);
43+ }
44+
45+ private:
46+ template <typename Buff = MutableBufferSequence>
47+ typename std::enable_if<std::is_same<Buff, azmq::message>::value, bool >::type do_perform_impl (socket_type& socket)
48+ {
49+ ec_ = boost::system::error_code ();
50+ bytes_transferred_ += socket_ops::receive (const_cast <azmq::message&>(buffers_), socket, flags_ | ZMQ_DONTWAIT, ec_);
51+ if (ec_)
52+ return !try_again ();
53+ return true ;
54+ }
55+
56+ template <typename Buff = MutableBufferSequence>
57+ typename std::enable_if<!std::is_same<Buff, azmq::message>::value, bool >::type do_perform_impl (socket_type& socket)
58+ {
3359 ec_ = boost::system::error_code ();
3460 bytes_transferred_ += socket_ops::receive (buffers_, socket, flags_ | ZMQ_DONTWAIT, ec_);
3561 if (ec_)
@@ -43,7 +69,7 @@ class receive_buffer_op_base : public reactor_op {
4369 }
4470
4571private:
46- MutableBufferSequence buffers_;
72+ typename std::conditional<std::is_same< MutableBufferSequence, azmq::message>::value, MutableBufferSequence const &, MutableBufferSequence>::type buffers_;
4773 flags_type flags_;
4874};
4975
@@ -56,14 +82,30 @@ class receive_buffer_op : public receive_buffer_op_base<MutableBufferSequence> {
5682 socket_ops::flags_type flags)
5783 : receive_buffer_op_base<MutableBufferSequence>(buffers, flags)
5884 , handler_(std::move(handler))
85+ , work_guard(boost::asio::make_work_guard(handler_))
5986 { }
6087
6188 virtual void do_complete () override {
62- handler_ (this ->ec_ , this ->bytes_transferred_ );
89+ #if BOOST_VERSION >= 107900
90+ auto alloc = boost::asio::get_associated_allocator (
91+ handler_, boost::asio::recycling_allocator<void >());
92+ #endif
93+ boost::asio::dispatch (work_guard.get_executor (),
94+ #if BOOST_VERSION >= 107900
95+ boost::asio::bind_allocator (alloc,
96+ #endif
97+ [ec_ = this ->ec_ , handler_ = std::move (handler_), bytes_transferred_ = this ->bytes_transferred_ ]() mutable {
98+ handler_ (ec_, bytes_transferred_);
99+ })
100+ #if BOOST_VERSION >= 107900
101+ )
102+ #endif
103+ ;
63104 }
64105
65106private:
66107 Handler handler_;
108+ boost::asio::executor_work_guard<typename boost::asio::associated_executor<Handler>::type> work_guard;
67109};
68110
69111template <typename MutableBufferSequence,
@@ -75,14 +117,30 @@ class receive_more_buffer_op : public receive_buffer_op_base<MutableBufferSequen
75117 socket_ops::flags_type flags)
76118 : receive_buffer_op_base<MutableBufferSequence>(buffers, flags)
77119 , handler_(std::move(handler))
120+ , work_guard(boost::asio::make_work_guard(handler_))
78121 { }
79122
80123 virtual void do_complete () override {
81- handler_ (this ->ec_ , std::make_pair (this ->bytes_transferred_ , this ->more ()));
124+ #if BOOST_VERSION >= 107900
125+ auto alloc = boost::asio::get_associated_allocator (
126+ handler_, boost::asio::recycling_allocator<void >());
127+ #endif
128+ boost::asio::dispatch (work_guard.get_executor (),
129+ #if BOOST_VERSION >= 107900
130+ boost::asio::bind_allocator (alloc,
131+ #endif
132+ [ec_ = this ->ec_ , handler_ = std::move (handler_), bytes_transferred_ = this ->bytes_transferred_ , more = this ->more ()]() mutable {
133+ handler_ (ec_, std::make_pair (bytes_transferred_, more));
134+ })
135+ #if BOOST_VERSION >= 107900
136+ )
137+ #endif
138+ ;
82139 }
83140
84141private:
85142 Handler handler_;
143+ boost::asio::executor_work_guard<typename boost::asio::associated_executor<Handler>::type> work_guard;
86144};
87145
88146class receive_op_base : public reactor_op {
@@ -111,14 +169,30 @@ class receive_op : public receive_op_base {
111169 socket_ops::flags_type flags)
112170 : receive_op_base(flags)
113171 , handler_(std::move(handler))
172+ , work_guard(boost::asio::make_work_guard(handler_))
114173 { }
115174
116175 virtual void do_complete () override {
117- handler_ (ec_, msg_, bytes_transferred_);
176+ #if BOOST_VERSION >= 107900
177+ auto alloc = boost::asio::get_associated_allocator (
178+ handler_, boost::asio::recycling_allocator<void >());
179+ #endif
180+ boost::asio::dispatch (work_guard.get_executor (),
181+ #if BOOST_VERSION >= 107900
182+ boost::asio::bind_allocator (alloc,
183+ #endif
184+ [ec_ = this ->ec_ , handler_ = std::move (handler_), msg_ = std::move (msg_), bytes_transferred_ = this ->bytes_transferred_ ]() mutable {
185+ handler_ (ec_, msg_, bytes_transferred_);
186+ })
187+ #if BOOST_VERSION >= 107900
188+ )
189+ #endif
190+ ;
118191 }
119192
120193private:
121194 Handler handler_;
195+ boost::asio::executor_work_guard<typename boost::asio::associated_executor<Handler>::type> work_guard;
122196};
123197} // namespace detail
124198} // namespace azmq
0 commit comments