1414#include " socket_ops.hpp"
1515#include " reactor_op.hpp"
1616
17+ #include < boost/version.hpp>
1718#include < boost/asio/io_service.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
1825
1926#include < zmq.h>
2027
2128#include < iterator>
29+ #include < type_traits>
2230
2331namespace azmq {
2432namespace detail {
@@ -31,6 +39,23 @@ class receive_buffer_op_base : public reactor_op {
3139 { }
3240
3341 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+ {
3459 ec_ = boost::system::error_code ();
3560 bytes_transferred_ += socket_ops::receive (buffers_, socket, flags_ | ZMQ_DONTWAIT, ec_);
3661 if (ec_)
@@ -44,7 +69,7 @@ class receive_buffer_op_base : public reactor_op {
4469 }
4570
4671private:
47- MutableBufferSequence buffers_;
72+ typename std::conditional<std::is_same< MutableBufferSequence, azmq::message>::value, MutableBufferSequence const &, MutableBufferSequence>::type buffers_;
4873 flags_type flags_;
4974};
5075
@@ -57,14 +82,30 @@ class receive_buffer_op : public receive_buffer_op_base<MutableBufferSequence> {
5782 socket_ops::flags_type flags)
5883 : receive_buffer_op_base<MutableBufferSequence>(buffers, flags)
5984 , handler_(std::move(handler))
85+ , work_guard(boost::asio::make_work_guard(handler_))
6086 { }
6187
6288 virtual void do_complete () override {
63- 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+ ;
64104 }
65105
66106private:
67107 Handler handler_;
108+ boost::asio::executor_work_guard<typename boost::asio::associated_executor<Handler>::type> work_guard;
68109};
69110
70111template <typename MutableBufferSequence,
@@ -76,14 +117,30 @@ class receive_more_buffer_op : public receive_buffer_op_base<MutableBufferSequen
76117 socket_ops::flags_type flags)
77118 : receive_buffer_op_base<MutableBufferSequence>(buffers, flags)
78119 , handler_(std::move(handler))
120+ , work_guard(boost::asio::make_work_guard(handler_))
79121 { }
80122
81123 virtual void do_complete () override {
82- 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+ ;
83139 }
84140
85141private:
86142 Handler handler_;
143+ boost::asio::executor_work_guard<typename boost::asio::associated_executor<Handler>::type> work_guard;
87144};
88145
89146class receive_op_base : public reactor_op {
@@ -112,14 +169,30 @@ class receive_op : public receive_op_base {
112169 socket_ops::flags_type flags)
113170 : receive_op_base(flags)
114171 , handler_(std::move(handler))
172+ , work_guard(boost::asio::make_work_guard(handler_))
115173 { }
116174
117175 virtual void do_complete () override {
118- 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+ ;
119191 }
120192
121193private:
122194 Handler handler_;
195+ boost::asio::executor_work_guard<typename boost::asio::associated_executor<Handler>::type> work_guard;
123196};
124197} // namespace detail
125198} // namespace azmq
0 commit comments