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:
Vinnie Falco
2018-04-10 08:03:04 -07:00
parent b4cb4f1fd3
commit 86342dd72b
18 changed files with 154 additions and 34 deletions
+12 -1
View File
@@ -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;
}