forked from boostorg/beast
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:
@@ -88,6 +88,13 @@ class echo_op
|
||||
// The stream to read and write to
|
||||
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
|
||||
// to perform next, starting from zero.
|
||||
int step = 0;
|
||||
@@ -109,6 +116,7 @@ class echo_op
|
||||
//
|
||||
explicit state(Handler const& handler, AsyncStream& stream_)
|
||||
: stream(stream_)
|
||||
, work(stream.get_executor())
|
||||
, buffer((std::numeric_limits<std::size_t>::max)(),
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
// Invoke the final handler. The implementation of `handler_ptr`
|
||||
// will deallocate the storage for the state before the handler
|
||||
// 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
|
||||
// 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);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user