mirror of
https://github.com/boostorg/beast.git
synced 2025-07-31 05:17:26 +02:00
Use executor_work_guard in composed operations:
fix #1076 As per Asio and Networking TS requirements, composed operations must maintain an object of type executor_work_guard for the executor associated with the I/O object, for the lifetime of the asynchronous operation. This is in addition to the requirement for maintaining an object of type executor_work_guard for the executor associated with the handler.
This commit is contained in:
@ -1,3 +1,9 @@
|
|||||||
|
Version 168:
|
||||||
|
|
||||||
|
* Use executor_work_guard in composed operations
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
Version 167:
|
Version 167:
|
||||||
|
|
||||||
* Revert: Tidy up calls to post()
|
* Revert: Tidy up calls to post()
|
||||||
|
@ -146,6 +146,9 @@ composed operations:
|
|||||||
__io_context__, the underlying stream may be accessed in a fashion
|
__io_context__, the underlying stream may be accessed in a fashion
|
||||||
that violates safety guarantees.
|
that violates safety guarantees.
|
||||||
|
|
||||||
|
* Forgetting to create an object of type __executor_work_guard__ with the
|
||||||
|
type of executor returned by the stream's `get_executor` member function.
|
||||||
|
|
||||||
* For operations which complete immediately (i.e. without calling an
|
* For operations which complete immediately (i.e. without calling an
|
||||||
intermediate initiating function), forgetting to use __post__ to
|
intermediate initiating function), forgetting to use __post__ to
|
||||||
invoke the final handler. This breaks the following initiating
|
invoke the final handler. This breaks the following initiating
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/asio/coroutine.hpp>
|
#include <boost/asio/coroutine.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/logic/tribool.hpp>
|
#include <boost/logic/tribool.hpp>
|
||||||
|
|
||||||
/** Return `true` if a buffer contains a TLS/SSL client handshake.
|
/** Return `true` if a buffer contains a TLS/SSL client handshake.
|
||||||
@ -319,6 +320,14 @@ class detect_ssl_op : public boost::asio::coroutine
|
|||||||
// be cheaply copied as needed by the implementation.
|
// be cheaply copied as needed by the implementation.
|
||||||
|
|
||||||
AsyncReadStream& stream_;
|
AsyncReadStream& stream_;
|
||||||
|
|
||||||
|
// Boost.Asio and the Networking TS require an object of
|
||||||
|
// type executor_work_guard<T>, where T is the type of
|
||||||
|
// executor returned by the stream's get_executor function,
|
||||||
|
// to persist for the duration of the asynchronous operation.
|
||||||
|
boost::asio::executor_work_guard<
|
||||||
|
decltype(std::declval<AsyncReadStream&>().get_executor())> work_;
|
||||||
|
|
||||||
DynamicBuffer& buffer_;
|
DynamicBuffer& buffer_;
|
||||||
Handler handler_;
|
Handler handler_;
|
||||||
boost::tribool result_ = false;
|
boost::tribool result_ = false;
|
||||||
@ -336,6 +345,7 @@ public:
|
|||||||
DynamicBuffer& buffer,
|
DynamicBuffer& buffer,
|
||||||
DeducedHandler&& handler)
|
DeducedHandler&& handler)
|
||||||
: stream_(stream)
|
: stream_(stream)
|
||||||
|
, work_(stream.get_executor())
|
||||||
, buffer_(buffer)
|
, buffer_(buffer)
|
||||||
, handler_(std::forward<DeducedHandler>(handler))
|
, handler_(std::forward<DeducedHandler>(handler))
|
||||||
{
|
{
|
||||||
|
@ -88,6 +88,13 @@ class echo_op
|
|||||||
// The stream to read and write to
|
// The stream to read and write to
|
||||||
AsyncStream& stream;
|
AsyncStream& stream;
|
||||||
|
|
||||||
|
// Boost.Asio and the Networking TS require an object of
|
||||||
|
// type executor_work_guard<T>, where T is the type of
|
||||||
|
// executor returned by the stream's get_executor function,
|
||||||
|
// to persist for the duration of the asynchronous operation.
|
||||||
|
boost::asio::executor_work_guard<
|
||||||
|
decltype(std::declval<AsyncStream&>().get_executor())> work;
|
||||||
|
|
||||||
// Indicates what step in the operation's state machine
|
// Indicates what step in the operation's state machine
|
||||||
// to perform next, starting from zero.
|
// to perform next, starting from zero.
|
||||||
int step = 0;
|
int step = 0;
|
||||||
@ -109,6 +116,7 @@ class echo_op
|
|||||||
//
|
//
|
||||||
explicit state(Handler const& handler, AsyncStream& stream_)
|
explicit state(Handler const& handler, AsyncStream& stream_)
|
||||||
: stream(stream_)
|
: stream(stream_)
|
||||||
|
, work(stream.get_executor())
|
||||||
, buffer((std::numeric_limits<std::size_t>::max)(),
|
, buffer((std::numeric_limits<std::size_t>::max)(),
|
||||||
boost::asio::get_associated_allocator(handler))
|
boost::asio::get_associated_allocator(handler))
|
||||||
{
|
{
|
||||||
@ -215,7 +223,6 @@ operator()(boost::beast::error_code ec, std::size_t bytes_transferred)
|
|||||||
p.buffer.consume(bytes_transferred);
|
p.buffer.consume(bytes_transferred);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoke the final handler. The implementation of `handler_ptr`
|
// Invoke the final handler. The implementation of `handler_ptr`
|
||||||
// will deallocate the storage for the state before the handler
|
// will deallocate the storage for the state before the handler
|
||||||
// is invoked. This is necessary to provide the
|
// is invoked. This is necessary to provide the
|
||||||
@ -226,6 +233,10 @@ operator()(boost::beast::error_code ec, std::size_t bytes_transferred)
|
|||||||
// from the `state`, they would have to be moved to the stack
|
// from the `state`, they would have to be moved to the stack
|
||||||
// first or else undefined behavior results.
|
// first or else undefined behavior results.
|
||||||
//
|
//
|
||||||
|
// The work guard is moved to the stack first, otherwise it would
|
||||||
|
// be destroyed before the handler is invoked.
|
||||||
|
//
|
||||||
|
auto work = std::move(p.work);
|
||||||
p_.invoke(ec);
|
p_.invoke(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <boost/beast/core/detail/config.hpp>
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
#include <boost/asio/associated_allocator.hpp>
|
#include <boost/asio/associated_allocator.hpp>
|
||||||
#include <boost/asio/associated_executor.hpp>
|
#include <boost/asio/associated_executor.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/handler_continuation_hook.hpp>
|
#include <boost/asio/handler_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/handler_invoke_hook.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
@ -31,10 +32,12 @@ template<class MutableBufferSequence, class Handler>
|
|||||||
class buffered_read_stream<
|
class buffered_read_stream<
|
||||||
Stream, DynamicBuffer>::read_some_op
|
Stream, DynamicBuffer>::read_some_op
|
||||||
{
|
{
|
||||||
int step_ = 0;
|
|
||||||
buffered_read_stream& s_;
|
buffered_read_stream& s_;
|
||||||
|
boost::asio::executor_work_guard<decltype(
|
||||||
|
std::declval<Stream&>().get_executor())> wg_;
|
||||||
MutableBufferSequence b_;
|
MutableBufferSequence b_;
|
||||||
Handler h_;
|
Handler h_;
|
||||||
|
int step_ = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
read_some_op(read_some_op&&) = default;
|
read_some_op(read_some_op&&) = default;
|
||||||
@ -45,6 +48,7 @@ public:
|
|||||||
buffered_read_stream& s,
|
buffered_read_stream& s,
|
||||||
MutableBufferSequence const& b)
|
MutableBufferSequence const& b)
|
||||||
: s_(s)
|
: s_(s)
|
||||||
|
, wg_(s_.get_executor())
|
||||||
, b_(b)
|
, b_(b)
|
||||||
, h_(std::forward<DeducedHandler>(h))
|
, h_(std::forward<DeducedHandler>(h))
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <boost/asio/associated_executor.hpp>
|
#include <boost/asio/associated_executor.hpp>
|
||||||
#include <boost/asio/async_result.hpp>
|
#include <boost/asio/async_result.hpp>
|
||||||
#include <boost/asio/basic_stream_socket.hpp>
|
#include <boost/asio/basic_stream_socket.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/handler_continuation_hook.hpp>
|
#include <boost/asio/handler_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/handler_invoke_hook.hpp>
|
||||||
#include <boost/asio/windows/overlapped_ptr.hpp>
|
#include <boost/asio/windows/overlapped_ptr.hpp>
|
||||||
@ -337,6 +338,8 @@ template<
|
|||||||
class write_some_win32_op
|
class write_some_win32_op
|
||||||
{
|
{
|
||||||
boost::asio::basic_stream_socket<Protocol>& sock_;
|
boost::asio::basic_stream_socket<Protocol>& sock_;
|
||||||
|
boost::asio::executor_work_guard<decltype(std::declval<
|
||||||
|
boost::asio::basic_stream_socket<Protocol>&>().get_executor())> wg_;
|
||||||
serializer<isRequest,
|
serializer<isRequest,
|
||||||
basic_file_body<file_win32>, Fields>& sr_;
|
basic_file_body<file_win32>, Fields>& sr_;
|
||||||
std::size_t bytes_transferred_ = 0;
|
std::size_t bytes_transferred_ = 0;
|
||||||
@ -354,6 +357,7 @@ public:
|
|||||||
serializer<isRequest,
|
serializer<isRequest,
|
||||||
basic_file_body<file_win32>,Fields>& sr)
|
basic_file_body<file_win32>,Fields>& sr)
|
||||||
: sock_(s)
|
: sock_(s)
|
||||||
|
, wg_(sock_.get_executor())
|
||||||
, sr_(sr)
|
, sr_(sr)
|
||||||
, h_(std::forward<DeducedHandler>(h))
|
, h_(std::forward<DeducedHandler>(h))
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <boost/asio/associated_allocator.hpp>
|
#include <boost/asio/associated_allocator.hpp>
|
||||||
#include <boost/asio/associated_executor.hpp>
|
#include <boost/asio/associated_executor.hpp>
|
||||||
#include <boost/asio/coroutine.hpp>
|
#include <boost/asio/coroutine.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/handler_continuation_hook.hpp>
|
#include <boost/asio/handler_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/handler_invoke_hook.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
@ -43,6 +44,8 @@ class read_some_op
|
|||||||
: public boost::asio::coroutine
|
: public boost::asio::coroutine
|
||||||
{
|
{
|
||||||
Stream& s_;
|
Stream& s_;
|
||||||
|
boost::asio::executor_work_guard<decltype(
|
||||||
|
std::declval<Stream&>().get_executor())> wg_;
|
||||||
DynamicBuffer& b_;
|
DynamicBuffer& b_;
|
||||||
basic_parser<isRequest, Derived>& p_;
|
basic_parser<isRequest, Derived>& p_;
|
||||||
std::size_t bytes_transferred_ = 0;
|
std::size_t bytes_transferred_ = 0;
|
||||||
@ -57,6 +60,7 @@ public:
|
|||||||
read_some_op(DeducedHandler&& h, Stream& s,
|
read_some_op(DeducedHandler&& h, Stream& s,
|
||||||
DynamicBuffer& b, basic_parser<isRequest, Derived>& p)
|
DynamicBuffer& b, basic_parser<isRequest, Derived>& p)
|
||||||
: s_(s)
|
: s_(s)
|
||||||
|
, wg_(s_.get_executor())
|
||||||
, b_(b)
|
, b_(b)
|
||||||
, p_(p)
|
, p_(p)
|
||||||
, h_(std::forward<DeducedHandler>(h))
|
, h_(std::forward<DeducedHandler>(h))
|
||||||
@ -170,10 +174,13 @@ operator()(
|
|||||||
|
|
||||||
upcall:
|
upcall:
|
||||||
if(! cont_)
|
if(! cont_)
|
||||||
return boost::asio::post(
|
{
|
||||||
|
BOOST_ASIO_CORO_YIELD
|
||||||
|
boost::asio::post(
|
||||||
s_.get_executor(),
|
s_.get_executor(),
|
||||||
bind_handler(std::move(h_),
|
bind_handler(std::move(*this),
|
||||||
ec, bytes_transferred_));
|
ec, bytes_transferred_));
|
||||||
|
}
|
||||||
h_(ec, bytes_transferred_);
|
h_(ec, bytes_transferred_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,6 +216,8 @@ class read_op
|
|||||||
: public boost::asio::coroutine
|
: public boost::asio::coroutine
|
||||||
{
|
{
|
||||||
Stream& s_;
|
Stream& s_;
|
||||||
|
boost::asio::executor_work_guard<decltype(
|
||||||
|
std::declval<Stream&>().get_executor())> wg_;
|
||||||
DynamicBuffer& b_;
|
DynamicBuffer& b_;
|
||||||
basic_parser<isRequest, Derived>& p_;
|
basic_parser<isRequest, Derived>& p_;
|
||||||
std::size_t bytes_transferred_ = 0;
|
std::size_t bytes_transferred_ = 0;
|
||||||
@ -224,6 +233,7 @@ public:
|
|||||||
DynamicBuffer& b, basic_parser<isRequest,
|
DynamicBuffer& b, basic_parser<isRequest,
|
||||||
Derived>& p)
|
Derived>& p)
|
||||||
: s_(s)
|
: s_(s)
|
||||||
|
, wg_(s_.get_executor())
|
||||||
, b_(b)
|
, b_(b)
|
||||||
, p_(p)
|
, p_(p)
|
||||||
, h_(std::forward<DeducedHandler>(h))
|
, h_(std::forward<DeducedHandler>(h))
|
||||||
@ -327,6 +337,8 @@ class read_msg_op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
Stream& s;
|
Stream& s;
|
||||||
|
boost::asio::executor_work_guard<decltype(
|
||||||
|
std::declval<Stream&>().get_executor())> wg;
|
||||||
DynamicBuffer& b;
|
DynamicBuffer& b;
|
||||||
message_type& m;
|
message_type& m;
|
||||||
parser_type p;
|
parser_type p;
|
||||||
@ -336,6 +348,7 @@ class read_msg_op
|
|||||||
data(Handler const&, Stream& s_,
|
data(Handler const&, Stream& s_,
|
||||||
DynamicBuffer& b_, message_type& m_)
|
DynamicBuffer& b_, message_type& m_)
|
||||||
: s(s_)
|
: s(s_)
|
||||||
|
, wg(s.get_executor())
|
||||||
, b(b_)
|
, b(b_)
|
||||||
, m(m_)
|
, m(m_)
|
||||||
, p(std::move(m))
|
, p(std::move(m))
|
||||||
@ -432,7 +445,10 @@ operator()(
|
|||||||
}
|
}
|
||||||
upcall:
|
upcall:
|
||||||
bytes_transferred = d.bytes_transferred;
|
bytes_transferred = d.bytes_transferred;
|
||||||
d_.invoke(ec, bytes_transferred);
|
{
|
||||||
|
auto wg = std::move(d.wg);
|
||||||
|
d_.invoke(ec, bytes_transferred);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <boost/beast/core/detail/config.hpp>
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
#include <boost/asio/associated_allocator.hpp>
|
#include <boost/asio/associated_allocator.hpp>
|
||||||
#include <boost/asio/associated_executor.hpp>
|
#include <boost/asio/associated_executor.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/handler_continuation_hook.hpp>
|
#include <boost/asio/handler_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/handler_invoke_hook.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
@ -38,6 +39,8 @@ template<
|
|||||||
class write_some_op
|
class write_some_op
|
||||||
{
|
{
|
||||||
Stream& s_;
|
Stream& s_;
|
||||||
|
boost::asio::executor_work_guard<decltype(
|
||||||
|
std::declval<Stream&>().get_executor())> wg_;
|
||||||
serializer<isRequest,Body, Fields>& sr_;
|
serializer<isRequest,Body, Fields>& sr_;
|
||||||
Handler h_;
|
Handler h_;
|
||||||
|
|
||||||
@ -74,6 +77,7 @@ public:
|
|||||||
write_some_op(DeducedHandler&& h, Stream& s,
|
write_some_op(DeducedHandler&& h, Stream& s,
|
||||||
serializer<isRequest, Body, Fields>& sr)
|
serializer<isRequest, Body, Fields>& sr)
|
||||||
: s_(s)
|
: s_(s)
|
||||||
|
, wg_(s_.get_executor())
|
||||||
, sr_(sr)
|
, sr_(sr)
|
||||||
, h_(std::forward<DeducedHandler>(h))
|
, h_(std::forward<DeducedHandler>(h))
|
||||||
{
|
{
|
||||||
@ -204,11 +208,13 @@ template<
|
|||||||
bool isRequest, class Body, class Fields>
|
bool isRequest, class Body, class Fields>
|
||||||
class write_op
|
class write_op
|
||||||
{
|
{
|
||||||
int state_ = 0;
|
|
||||||
Stream& s_;
|
Stream& s_;
|
||||||
|
boost::asio::executor_work_guard<decltype(
|
||||||
|
std::declval<Stream&>().get_executor())> wg_;
|
||||||
serializer<isRequest, Body, Fields>& sr_;
|
serializer<isRequest, Body, Fields>& sr_;
|
||||||
std::size_t bytes_transferred_ = 0;
|
std::size_t bytes_transferred_ = 0;
|
||||||
Handler h_;
|
Handler h_;
|
||||||
|
int state_ = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
write_op(write_op&&) = default;
|
write_op(write_op&&) = default;
|
||||||
@ -218,6 +224,7 @@ public:
|
|||||||
write_op(DeducedHandler&& h, Stream& s,
|
write_op(DeducedHandler&& h, Stream& s,
|
||||||
serializer<isRequest, Body, Fields>& sr)
|
serializer<isRequest, Body, Fields>& sr)
|
||||||
: s_(s)
|
: s_(s)
|
||||||
|
, wg_(s_.get_executor())
|
||||||
, sr_(sr)
|
, sr_(sr)
|
||||||
, h_(std::forward<DeducedHandler>(h))
|
, h_(std::forward<DeducedHandler>(h))
|
||||||
{
|
{
|
||||||
@ -321,11 +328,14 @@ class write_msg_op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
Stream& s;
|
Stream& s;
|
||||||
|
boost::asio::executor_work_guard<decltype(
|
||||||
|
std::declval<Stream&>().get_executor())> wg;
|
||||||
serializer<isRequest, Body, Fields> sr;
|
serializer<isRequest, Body, Fields> sr;
|
||||||
|
|
||||||
data(Handler const&, Stream& s_, message<
|
data(Handler const&, Stream& s_, message<
|
||||||
isRequest, Body, Fields>& m_)
|
isRequest, Body, Fields>& m_)
|
||||||
: s(s_)
|
: s(s_)
|
||||||
|
, wg(s.get_executor())
|
||||||
, sr(m_)
|
, sr(m_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -405,6 +415,7 @@ write_msg_op<
|
|||||||
Stream, Handler, isRequest, Body, Fields>::
|
Stream, Handler, isRequest, Body, Fields>::
|
||||||
operator()(error_code ec, std::size_t bytes_transferred)
|
operator()(error_code ec, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
|
auto wg = std::move(d_->wg);
|
||||||
d_.invoke(ec, bytes_transferred);
|
d_.invoke(ec, bytes_transferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <boost/asio/coroutine.hpp>
|
#include <boost/asio/coroutine.hpp>
|
||||||
#include <boost/asio/associated_allocator.hpp>
|
#include <boost/asio/associated_allocator.hpp>
|
||||||
#include <boost/asio/associated_executor.hpp>
|
#include <boost/asio/associated_executor.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/handler_continuation_hook.hpp>
|
#include <boost/asio/handler_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/handler_invoke_hook.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
@ -43,6 +44,8 @@ class stream<NextLayer, deflateSupported>::response_op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer, deflateSupported>& ws;
|
stream<NextLayer, deflateSupported>& ws;
|
||||||
|
boost::asio::executor_work_guard<decltype(std::declval<
|
||||||
|
stream<NextLayer, deflateSupported>&>().get_executor())> wg;
|
||||||
error_code result;
|
error_code result;
|
||||||
response_type res;
|
response_type res;
|
||||||
|
|
||||||
@ -54,6 +57,7 @@ class stream<NextLayer, deflateSupported>::response_op
|
|||||||
http::basic_fields<Allocator>> const& req,
|
http::basic_fields<Allocator>> const& req,
|
||||||
Decorator const& decorator)
|
Decorator const& decorator)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
|
, wg(ws.get_executor())
|
||||||
, res(ws_.build_response(req, decorator, result))
|
, res(ws_.build_response(req, decorator, result))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -137,7 +141,10 @@ operator()(
|
|||||||
d.ws.do_pmd_config(d.res, is_deflate_supported{});
|
d.ws.do_pmd_config(d.res, is_deflate_supported{});
|
||||||
d.ws.open(role_type::server);
|
d.ws.open(role_type::server);
|
||||||
}
|
}
|
||||||
d_.invoke(ec);
|
{
|
||||||
|
auto wg = std::move(d.wg);
|
||||||
|
d_.invoke(ec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,6 +160,8 @@ class stream<NextLayer, deflateSupported>::accept_op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer, deflateSupported>& ws;
|
stream<NextLayer, deflateSupported>& ws;
|
||||||
|
boost::asio::executor_work_guard<decltype(std::declval<
|
||||||
|
stream<NextLayer, deflateSupported>&>().get_executor())> wg;
|
||||||
Decorator decorator;
|
Decorator decorator;
|
||||||
http::request_parser<http::empty_body> p;
|
http::request_parser<http::empty_body> p;
|
||||||
data(
|
data(
|
||||||
@ -160,6 +169,7 @@ class stream<NextLayer, deflateSupported>::accept_op
|
|||||||
stream<NextLayer, deflateSupported>& ws_,
|
stream<NextLayer, deflateSupported>& ws_,
|
||||||
Decorator const& decorator_)
|
Decorator const& decorator_)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
|
, wg(ws.get_executor())
|
||||||
, decorator(decorator_)
|
, decorator(decorator_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -284,6 +294,7 @@ operator()(error_code ec, std::size_t)
|
|||||||
auto& ws = d.ws;
|
auto& ws = d.ws;
|
||||||
auto const req = d.p.release();
|
auto const req = d.p.release();
|
||||||
auto const decorator = d.decorator;
|
auto const decorator = d.decorator;
|
||||||
|
auto wg = std::move(d.wg);
|
||||||
#if 1
|
#if 1
|
||||||
return response_op<Handler>{
|
return response_op<Handler>{
|
||||||
d_.release_handler(),
|
d_.release_handler(),
|
||||||
@ -297,7 +308,10 @@ operator()(error_code ec, std::size_t)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
d_.invoke(ec);
|
{
|
||||||
|
auto wg = std::move(d.wg);
|
||||||
|
d_.invoke(ec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <boost/asio/associated_allocator.hpp>
|
#include <boost/asio/associated_allocator.hpp>
|
||||||
#include <boost/asio/associated_executor.hpp>
|
#include <boost/asio/associated_executor.hpp>
|
||||||
#include <boost/asio/coroutine.hpp>
|
#include <boost/asio/coroutine.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/handler_continuation_hook.hpp>
|
#include <boost/asio/handler_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/handler_invoke_hook.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
@ -43,6 +44,8 @@ class stream<NextLayer, deflateSupported>::close_op
|
|||||||
struct state
|
struct state
|
||||||
{
|
{
|
||||||
stream<NextLayer, deflateSupported>& ws;
|
stream<NextLayer, deflateSupported>& ws;
|
||||||
|
boost::asio::executor_work_guard<decltype(std::declval<
|
||||||
|
stream<NextLayer, deflateSupported>&>().get_executor())> wg;
|
||||||
detail::frame_buffer fb;
|
detail::frame_buffer fb;
|
||||||
error_code ev;
|
error_code ev;
|
||||||
bool cont = false;
|
bool cont = false;
|
||||||
@ -52,6 +55,7 @@ class stream<NextLayer, deflateSupported>::close_op
|
|||||||
stream<NextLayer, deflateSupported>& ws_,
|
stream<NextLayer, deflateSupported>& ws_,
|
||||||
close_reason const& cr)
|
close_reason const& cr)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
|
, wg(ws.get_executor())
|
||||||
{
|
{
|
||||||
// Serialize the close frame
|
// Serialize the close frame
|
||||||
ws.template write_close<
|
ws.template write_close<
|
||||||
@ -303,12 +307,15 @@ operator()(
|
|||||||
d.ws.paused_wr_.maybe_invoke();
|
d.ws.paused_wr_.maybe_invoke();
|
||||||
if(! d.cont)
|
if(! d.cont)
|
||||||
{
|
{
|
||||||
auto& ws = d.ws;
|
BOOST_ASIO_CORO_YIELD
|
||||||
return boost::asio::post(
|
boost::asio::post(
|
||||||
ws.stream_.get_executor(),
|
d.ws.get_executor(),
|
||||||
bind_handler(d_.release_handler(), ec));
|
bind_handler(std::move(*this), ec));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto wg = std::move(d.wg);
|
||||||
|
d_.invoke(ec);
|
||||||
}
|
}
|
||||||
d_.invoke(ec);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <boost/asio/associated_allocator.hpp>
|
#include <boost/asio/associated_allocator.hpp>
|
||||||
#include <boost/asio/associated_executor.hpp>
|
#include <boost/asio/associated_executor.hpp>
|
||||||
#include <boost/asio/coroutine.hpp>
|
#include <boost/asio/coroutine.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/handler_continuation_hook.hpp>
|
#include <boost/asio/handler_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/handler_invoke_hook.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
@ -42,6 +43,8 @@ class stream<NextLayer, deflateSupported>::handshake_op
|
|||||||
struct data
|
struct data
|
||||||
{
|
{
|
||||||
stream<NextLayer, deflateSupported>& ws;
|
stream<NextLayer, deflateSupported>& ws;
|
||||||
|
boost::asio::executor_work_guard<decltype(std::declval<
|
||||||
|
stream<NextLayer, deflateSupported>&>().get_executor())> wg;
|
||||||
response_type* res_p;
|
response_type* res_p;
|
||||||
detail::sec_ws_key_type key;
|
detail::sec_ws_key_type key;
|
||||||
http::request<http::empty_body> req;
|
http::request<http::empty_body> req;
|
||||||
@ -56,6 +59,7 @@ class stream<NextLayer, deflateSupported>::handshake_op
|
|||||||
string_view target,
|
string_view target,
|
||||||
Decorator const& decorator)
|
Decorator const& decorator)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
|
, wg(ws.get_executor())
|
||||||
, res_p(res_p_)
|
, res_p(res_p_)
|
||||||
, req(ws.build_request(key,
|
, req(ws.build_request(key,
|
||||||
host, target, decorator))
|
host, target, decorator))
|
||||||
@ -155,7 +159,10 @@ operator()(error_code ec, std::size_t)
|
|||||||
if(d.res_p)
|
if(d.res_p)
|
||||||
swap(d.res, *d.res_p);
|
swap(d.res, *d.res_p);
|
||||||
upcall:
|
upcall:
|
||||||
d_.invoke(ec);
|
{
|
||||||
|
auto wg = std::move(d.wg);
|
||||||
|
d_.invoke(ec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <boost/asio/associated_allocator.hpp>
|
#include <boost/asio/associated_allocator.hpp>
|
||||||
#include <boost/asio/associated_executor.hpp>
|
#include <boost/asio/associated_executor.hpp>
|
||||||
#include <boost/asio/coroutine.hpp>
|
#include <boost/asio/coroutine.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/handler_continuation_hook.hpp>
|
#include <boost/asio/handler_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/handler_invoke_hook.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
@ -41,6 +42,8 @@ class stream<NextLayer, deflateSupported>::ping_op
|
|||||||
struct state
|
struct state
|
||||||
{
|
{
|
||||||
stream<NextLayer, deflateSupported>& ws;
|
stream<NextLayer, deflateSupported>& ws;
|
||||||
|
boost::asio::executor_work_guard<decltype(std::declval<
|
||||||
|
stream<NextLayer, deflateSupported>&>().get_executor())> wg;
|
||||||
detail::frame_buffer fb;
|
detail::frame_buffer fb;
|
||||||
|
|
||||||
state(
|
state(
|
||||||
@ -49,6 +52,7 @@ class stream<NextLayer, deflateSupported>::ping_op
|
|||||||
detail::opcode op,
|
detail::opcode op,
|
||||||
ping_data const& payload)
|
ping_data const& payload)
|
||||||
: ws(ws_)
|
: ws(ws_)
|
||||||
|
, wg(ws.get_executor())
|
||||||
{
|
{
|
||||||
// Serialize the control frame
|
// Serialize the control frame
|
||||||
ws.template write_ping<
|
ws.template write_ping<
|
||||||
@ -172,7 +176,10 @@ operator()(error_code ec, std::size_t)
|
|||||||
d.ws.paused_close_.maybe_invoke() ||
|
d.ws.paused_close_.maybe_invoke() ||
|
||||||
d.ws.paused_rd_.maybe_invoke() ||
|
d.ws.paused_rd_.maybe_invoke() ||
|
||||||
d.ws.paused_wr_.maybe_invoke();
|
d.ws.paused_wr_.maybe_invoke();
|
||||||
d_.invoke(ec);
|
{
|
||||||
|
auto wg = std::move(d.wg);
|
||||||
|
d_.invoke(ec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <boost/asio/associated_allocator.hpp>
|
#include <boost/asio/associated_allocator.hpp>
|
||||||
#include <boost/asio/associated_executor.hpp>
|
#include <boost/asio/associated_executor.hpp>
|
||||||
#include <boost/asio/coroutine.hpp>
|
#include <boost/asio/coroutine.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/handler_continuation_hook.hpp>
|
#include <boost/asio/handler_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/handler_invoke_hook.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
@ -82,6 +83,8 @@ class stream<NextLayer, deflateSupported>::read_some_op
|
|||||||
{
|
{
|
||||||
Handler h_;
|
Handler h_;
|
||||||
stream<NextLayer, deflateSupported>& ws_;
|
stream<NextLayer, deflateSupported>& ws_;
|
||||||
|
boost::asio::executor_work_guard<decltype(std::declval<
|
||||||
|
stream<NextLayer, deflateSupported>&>().get_executor())> wg_;
|
||||||
MutableBufferSequence bs_;
|
MutableBufferSequence bs_;
|
||||||
buffers_suffix<MutableBufferSequence> cb_;
|
buffers_suffix<MutableBufferSequence> cb_;
|
||||||
std::size_t bytes_written_ = 0;
|
std::size_t bytes_written_ = 0;
|
||||||
@ -103,6 +106,7 @@ public:
|
|||||||
MutableBufferSequence const& bs)
|
MutableBufferSequence const& bs)
|
||||||
: h_(std::forward<DeducedHandler>(h))
|
: h_(std::forward<DeducedHandler>(h))
|
||||||
, ws_(ws)
|
, ws_(ws)
|
||||||
|
, wg_(ws_.get_executor())
|
||||||
, bs_(bs)
|
, bs_(bs)
|
||||||
, cb_(bs)
|
, cb_(bs)
|
||||||
, code_(close_code::none)
|
, code_(close_code::none)
|
||||||
@ -700,10 +704,13 @@ operator()(
|
|||||||
ws_.paused_ping_.maybe_invoke() ||
|
ws_.paused_ping_.maybe_invoke() ||
|
||||||
ws_.paused_wr_.maybe_invoke();
|
ws_.paused_wr_.maybe_invoke();
|
||||||
if(! cont_)
|
if(! cont_)
|
||||||
return boost::asio::post(
|
{
|
||||||
ws_.stream_.get_executor(),
|
BOOST_ASIO_CORO_YIELD
|
||||||
bind_handler(std::move(h_),
|
boost::asio::post(
|
||||||
|
ws_.get_executor(),
|
||||||
|
bind_handler(std::move(*this),
|
||||||
ec, bytes_written_));
|
ec, bytes_written_));
|
||||||
|
}
|
||||||
h_(ec, bytes_written_);
|
h_(ec, bytes_written_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -719,6 +726,8 @@ class stream<NextLayer, deflateSupported>::read_op
|
|||||||
{
|
{
|
||||||
Handler h_;
|
Handler h_;
|
||||||
stream<NextLayer, deflateSupported>& ws_;
|
stream<NextLayer, deflateSupported>& ws_;
|
||||||
|
boost::asio::executor_work_guard<decltype(std::declval<
|
||||||
|
stream<NextLayer, deflateSupported>&>().get_executor())> wg_;
|
||||||
DynamicBuffer& b_;
|
DynamicBuffer& b_;
|
||||||
std::size_t limit_;
|
std::size_t limit_;
|
||||||
std::size_t bytes_written_ = 0;
|
std::size_t bytes_written_ = 0;
|
||||||
@ -740,6 +749,7 @@ public:
|
|||||||
bool some)
|
bool some)
|
||||||
: h_(std::forward<DeducedHandler>(h))
|
: h_(std::forward<DeducedHandler>(h))
|
||||||
, ws_(ws)
|
, ws_(ws)
|
||||||
|
, wg_(ws_.get_executor())
|
||||||
, b_(b)
|
, b_(b)
|
||||||
, limit_(limit ? limit : (
|
, limit_(limit ? limit : (
|
||||||
std::numeric_limits<std::size_t>::max)())
|
std::numeric_limits<std::size_t>::max)())
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <boost/asio/associated_allocator.hpp>
|
#include <boost/asio/associated_allocator.hpp>
|
||||||
#include <boost/asio/associated_executor.hpp>
|
#include <boost/asio/associated_executor.hpp>
|
||||||
#include <boost/asio/coroutine.hpp>
|
#include <boost/asio/coroutine.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/handler_continuation_hook.hpp>
|
#include <boost/asio/handler_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/handler_invoke_hook.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
@ -34,6 +35,8 @@ class teardown_tcp_op : public boost::asio::coroutine
|
|||||||
|
|
||||||
Handler h_;
|
Handler h_;
|
||||||
socket_type& s_;
|
socket_type& s_;
|
||||||
|
boost::asio::executor_work_guard<decltype(std::declval<
|
||||||
|
socket_type&>().get_executor())> wg_;
|
||||||
role_type role_;
|
role_type role_;
|
||||||
bool nb_;
|
bool nb_;
|
||||||
|
|
||||||
@ -48,6 +51,7 @@ public:
|
|||||||
role_type role)
|
role_type role)
|
||||||
: h_(std::forward<DeducedHandler>(h))
|
: h_(std::forward<DeducedHandler>(h))
|
||||||
, s_(s)
|
, s_(s)
|
||||||
|
, wg_(s_.get_executor())
|
||||||
, role_(role)
|
, role_(role)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <boost/asio/associated_allocator.hpp>
|
#include <boost/asio/associated_allocator.hpp>
|
||||||
#include <boost/asio/associated_executor.hpp>
|
#include <boost/asio/associated_executor.hpp>
|
||||||
#include <boost/asio/coroutine.hpp>
|
#include <boost/asio/coroutine.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/handler_continuation_hook.hpp>
|
#include <boost/asio/handler_continuation_hook.hpp>
|
||||||
#include <boost/asio/handler_invoke_hook.hpp>
|
#include <boost/asio/handler_invoke_hook.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
@ -141,6 +142,8 @@ class stream<NextLayer, deflateSupported>::write_some_op
|
|||||||
{
|
{
|
||||||
Handler h_;
|
Handler h_;
|
||||||
stream<NextLayer, deflateSupported>& ws_;
|
stream<NextLayer, deflateSupported>& ws_;
|
||||||
|
boost::asio::executor_work_guard<decltype(std::declval<
|
||||||
|
stream<NextLayer, deflateSupported>&>().get_executor())> wg_;
|
||||||
buffers_suffix<Buffers> cb_;
|
buffers_suffix<Buffers> cb_;
|
||||||
detail::frame_header fh_;
|
detail::frame_header fh_;
|
||||||
detail::prepared_key key_;
|
detail::prepared_key key_;
|
||||||
@ -166,6 +169,7 @@ public:
|
|||||||
Buffers const& bs)
|
Buffers const& bs)
|
||||||
: h_(std::forward<DeducedHandler>(h))
|
: h_(std::forward<DeducedHandler>(h))
|
||||||
, ws_(ws)
|
, ws_(ws)
|
||||||
|
, wg_(ws_.get_executor())
|
||||||
, cb_(bs)
|
, cb_(bs)
|
||||||
, fin_(fin)
|
, fin_(fin)
|
||||||
{
|
{
|
||||||
@ -569,9 +573,12 @@ operator()(
|
|||||||
ws_.paused_rd_.maybe_invoke() ||
|
ws_.paused_rd_.maybe_invoke() ||
|
||||||
ws_.paused_ping_.maybe_invoke();
|
ws_.paused_ping_.maybe_invoke();
|
||||||
if(! cont_)
|
if(! cont_)
|
||||||
return boost::asio::post(
|
{
|
||||||
ws_.stream_.get_executor(),
|
BOOST_ASIO_CORO_YIELD
|
||||||
bind_handler(std::move(h_), ec, bytes_transferred_));
|
boost::asio::post(
|
||||||
|
ws_.get_executor(),
|
||||||
|
bind_handler(std::move(*this), ec, bytes_transferred_));
|
||||||
|
}
|
||||||
h_(ec, bytes_transferred_);
|
h_(ec, bytes_transferred_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <boost/beast/test/stream.hpp>
|
#include <boost/beast/test/stream.hpp>
|
||||||
#include <boost/beast/test/yield_to.hpp>
|
#include <boost/beast/test/yield_to.hpp>
|
||||||
#include <boost/beast/unit_test/suite.hpp>
|
#include <boost/beast/unit_test/suite.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/spawn.hpp>
|
#include <boost/asio/spawn.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
@ -71,9 +72,8 @@ public:
|
|||||||
|
|
||||||
std::ostream& log_;
|
std::ostream& log_;
|
||||||
boost::asio::io_context ioc_;
|
boost::asio::io_context ioc_;
|
||||||
boost::optional<
|
boost::asio::executor_work_guard<
|
||||||
boost::asio::executor_work_guard<
|
boost::asio::io_context::executor_type> work_;
|
||||||
boost::asio::io_context::executor_type>> work_;
|
|
||||||
static_buffer<buf_size> buffer_;
|
static_buffer<buf_size> buffer_;
|
||||||
test::stream ts_;
|
test::stream ts_;
|
||||||
std::thread t_;
|
std::thread t_;
|
||||||
@ -115,7 +115,7 @@ public:
|
|||||||
|
|
||||||
~echo_server()
|
~echo_server()
|
||||||
{
|
{
|
||||||
work_ = boost::none;
|
work_.reset();
|
||||||
t_.join();
|
t_.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <boost/beast/test/fail_counter.hpp>
|
#include <boost/beast/test/fail_counter.hpp>
|
||||||
#include <boost/asio/async_result.hpp>
|
#include <boost/asio/async_result.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
@ -697,9 +698,8 @@ class stream::read_op_impl : public stream::read_op
|
|||||||
state& s_;
|
state& s_;
|
||||||
Buffers b_;
|
Buffers b_;
|
||||||
Handler h_;
|
Handler h_;
|
||||||
boost::optional<
|
boost::asio::executor_work_guard<
|
||||||
boost::asio::executor_work_guard<
|
boost::asio::io_context::executor_type> work_;
|
||||||
boost::asio::io_context::executor_type>> work_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
lambda(lambda&&) = default;
|
lambda(lambda&&) = default;
|
||||||
@ -720,7 +720,7 @@ class stream::read_op_impl : public stream::read_op
|
|||||||
boost::asio::post(
|
boost::asio::post(
|
||||||
s_.ioc.get_executor(),
|
s_.ioc.get_executor(),
|
||||||
std::move(*this));
|
std::move(*this));
|
||||||
work_ = boost::none;
|
work_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
#ifndef BOOST_BEAST_TEST_YIELD_TO_HPP
|
#ifndef BOOST_BEAST_TEST_YIELD_TO_HPP
|
||||||
#define BOOST_BEAST_TEST_YIELD_TO_HPP
|
#define BOOST_BEAST_TEST_YIELD_TO_HPP
|
||||||
|
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <boost/asio/spawn.hpp>
|
#include <boost/asio/spawn.hpp>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@ -35,9 +35,8 @@ protected:
|
|||||||
boost::asio::io_context ioc_;
|
boost::asio::io_context ioc_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::optional<
|
boost::asio::executor_work_guard<
|
||||||
boost::asio::executor_work_guard<
|
boost::asio::io_context::executor_type> work_;
|
||||||
boost::asio::io_context::executor_type>> work_;
|
|
||||||
std::vector<std::thread> threads_;
|
std::vector<std::thread> threads_;
|
||||||
std::mutex m_;
|
std::mutex m_;
|
||||||
std::condition_variable cv_;
|
std::condition_variable cv_;
|
||||||
@ -60,7 +59,7 @@ public:
|
|||||||
|
|
||||||
~enable_yield_to()
|
~enable_yield_to()
|
||||||
{
|
{
|
||||||
work_ = boost::none;
|
work_.reset();
|
||||||
for(auto& t : threads_)
|
for(auto& t : threads_)
|
||||||
t.join();
|
t.join();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user