Use async_op_base::invoke

This commit is contained in:
Vinnie Falco
2019-02-15 15:47:36 -08:00
parent f41363c60c
commit 2e62f25701
7 changed files with 30 additions and 81 deletions

View File

@ -302,21 +302,13 @@ async_echo(
// directly invoke the completion handler otherwise it could
// lead to unfairness, starvation, or stack overflow. Therefore,
// if cont == false (meaning, that the call stack still includes
// the frame of the initiating function) then use `net::post`
// to cause us to be called again after the initiating function
// returns. The function `bind_handler` works similarly to
// `std::bind`, allowing bound arguments to be passed to our
// completion handler during the dispatch, but also takes care
// of forwarding the allocator and executor customization points
// in the returned call wrapper.
// the frame of the initiating function) then we need to use
// `net::post` to cause us to be called again after the initiating
// function. The function `async_op_base::invoke` takes care of
// calling the final completion handler, using post if the
// first argument is false, otherwise invoking it directly.
if(! cont)
yield net::post(beast::bind_handler(std::move(*this), ec));
// The function `async_op_base::invoke` takes care of calling
// the final completion handler.
this->invoke_now(ec);
this->invoke(cont, ec);
}
}
};

View File

@ -84,13 +84,13 @@ namespace beast {
using handler_type = BOOST_ASIO_HANDLER_TYPE(ReadHandler, void(error_code, std::size_t));
using base_type = async_op_base<handler_type, typename AsyncReadStream::executor_type>;
struct read_op : base_type
struct op : base_type
{
AsyncReadStream& stream_;
net::mutable_buffer buffer_;
std::size_t total_bytes_transferred_;
read_op(
op(
AsyncReadStream& stream,
net::mutable_buffer buffer,
handler_type& handler)
@ -112,22 +112,17 @@ namespace beast {
if(! ec && buffer_.size() > 0)
return stream_.async_read_some(buffer_, std::move(*this));
// If this is first invocation, we have to post to the executor. Otherwise the
// handler would be invoked before the call to async_read returns, which is disallowed.
if(! is_continuation)
{
// Issue a zero-sized read so our handler runs "as-if" posted using net::post().
// This technique is used to reduce the number of function template instantiations.
return stream_.async_read_some(net::mutable_buffer(buffer_.data(), 0), std::move(*this));
}
// Call the completion handler with the result. If `is_continuation` is
// false, which happens on the first time through this function, then
// `net::post` will be used to call the completion handler, otherwise
// the completion handler will be invoked directly.
// Call the completion handler with the result
this->invoke_now(ec, total_bytes_transferred_);
this->invoke(is_continuation, ec, total_bytes_transferred_);
}
};
net::async_completion<ReadHandler, void(error_code, std::size_t)> init{handler};
read_op(stream, buffer, init.completion_handler);
op(stream, buffer, init.completion_handler);
return init.result.get();
}
@ -341,15 +336,20 @@ public:
invoke(bool is_continuation, Args&&... args)
{
this->before_invoke_hook();
wg1_.reset();
if(! is_continuation)
{
net::post(net::bind_executor(
wg1_.get_executor(),
beast::bind_front_handler(
std::move(h_),
std::forward<Args>(args)...)));
wg1_.reset();
}
else
{
wg1_.reset();
h_(std::forward<Args>(args)...);
}
}
/** Invoke the final completion handler.

View File

@ -89,14 +89,7 @@ public:
b_.commit(bytes_transferred);
total_ += bytes_transferred;
}
if(! cont)
{
BOOST_ASIO_CORO_YIELD
net::post(s_.get_executor(),
beast::bind_front_handler(
std::move(*this), ec, total_));
}
this->invoke_now(ec, total_);
this->invoke(cont, ec, total_);
}
}
};
@ -197,14 +190,7 @@ public:
limit_ = cond_(ec, total_, b_);
}
}
if(! cont)
{
BOOST_ASIO_CORO_YIELD
net::post(s_.get_executor(),
beast::bind_front_handler(
std::move(*this), ec, total_));
}
this->invoke_now(ec, total_);
this->invoke(cont, ec, total_);
}
}

View File

@ -246,14 +246,7 @@ public:
d_.ws.impl_->paused_rd.maybe_invoke() ||
d_.ws.impl_->paused_ping.maybe_invoke() ||
d_.ws.impl_->paused_wr.maybe_invoke();
if(! d_.cont)
{
BOOST_ASIO_CORO_YIELD
net::post(
d_.ws.get_executor(),
beast::bind_front_handler(std::move(*this), ec));
}
this->invoke_now(ec);
this->invoke(d_.cont, ec);
}
}
};

View File

@ -609,15 +609,7 @@ public:
impl.paused_close.maybe_invoke() ||
impl.paused_ping.maybe_invoke() ||
impl.paused_wr.maybe_invoke();
if(! cont_)
{
BOOST_ASIO_CORO_YIELD
net::post(
ws_.get_executor(),
beast::bind_front_handler(std::move(*this),
ec, bytes_written_));
}
this->invoke_now(ec, bytes_written_);
this->invoke(cont_, ec, bytes_written_);
}
}
};

View File

@ -422,16 +422,7 @@ operator()(
ws_.impl_->paused_close.maybe_invoke() ||
ws_.impl_->paused_rd.maybe_invoke() ||
ws_.impl_->paused_ping.maybe_invoke();
if(! cont_)
{
BOOST_ASIO_CORO_YIELD
net::post(
ws_.get_executor(),
beast::bind_front_handler(
std::move(*this),
ec, bytes_transferred_));
}
this->invoke_now(ec, bytes_transferred_);
this->invoke(cont_, ec, bytes_transferred_);
}
}

View File

@ -615,17 +615,12 @@ public:
if(! ec && buffer_.size() > 0)
return stream_.async_read_some(buffer_, std::move(*this));
// If this is first invocation, we have to post to the executor. Otherwise the
// handler would be invoked before the call to async_read returns, which is disallowed.
if(! is_continuation)
{
// Issue a zero-sized read so our handler runs "as-if" posted using net::post().
// This technique is used to reduce the number of function template instantiations.
return stream_.async_read_some(net::mutable_buffer(buffer_.data(), 0), std::move(*this));
}
// Call the completion handler with the result. If `is_continuation` is
// false, which happens on the first time through this function, then
// `net::post` will be used to call the completion handler, otherwise
// the completion handler will be invoked directly.
// Call the completion handler with the result
this->invoke_now(ec, total_bytes_transferred_);
this->invoke(is_continuation, ec, total_bytes_transferred_);
}
};