he *_*led 4 c++ boost boost-asio boost-beast
在 Boost 1.66 中,Asio弃用了asio_handler_is_continuation钩子函数,促进了defer函数的使用。该 defer函数的行为似乎与postasio_handler_is_continuation==true 时的行为完全相同。但是,使用方式与使用defer方式不同asio_handler_is_continuation,我不确定如何正确使用defer。
编辑:我认为下面的示例过于冗长,无法清楚地表达我的意思。这是较短的示例:
async_read_until(stream, read_buffer, "\r\n",
[](boost::system::error_code ec, std::size_t bytes_transferred)
{
if(!ec)
async_write(stream, write_buffer, some_handler);
})
Run Code Online (Sandbox Code Playgroud)
现在async_read_until完成后,传递的 lambda 处理程序将使用某种等效于boost::asio::post. 但是async_write在 lambda 处理程序内部是上次异步任务的延续,所以我想调用 lambda 处理程序来利用defer优化。
有没有办法使用defer(而不是post)来调用上面示例中的 lambda 处理程序?
ORIGINAL POST:我正在尝试编写一个async_echo类似于野兽文档中的简单启动函数,除了调用的部分boost::asio::async_write将作为延续调用。为了实现这一点,先前的中间操作boost::asio::async_read_until必须调用处理程序*this作为延续。
这是我在野兽文档的 async_echo 示例中所指的部分:
template<class AsyncStream, class Handler>
void echo_op<AsyncStream, Handler>::
operator()(boost::beast::error_code ec, std::size_t bytes_transferred)
{
// Store a reference to our state. The address of the state won't
// change, and this solves the problem where dereferencing the
// data member is undefined after a move.
auto& p = *p_;
// Now perform the next step in the state machine
switch(ec ? 2 : p.step)
{
// initial entry
case 0:
// read up to the first newline
p.step = 1;
return boost::asio::async_read_until(p.stream, p.buffer, "\r", std::move(*this));
case 1:
// write everything back
p.step = 2;
// async_read_until could have read past the newline,
// use buffers_prefix to make sure we only send one line
return boost::asio::async_write(p.stream,
boost::beast::buffers_prefix(bytes_transferred, p.buffer.data()), std::move(*this));
case 2:
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
// destroy-before-invocation guarantee on handler memory
// customizations.
//
// If we wanted to pass any arguments to the handler which come
// from the `state`, they would have to be moved to the stack
// first or else undefined behavior results.
//
p_.invoke(ec);
return;
}
Run Code Online (Sandbox Code Playgroud)
在 1.66 天之前,我可以简单地钩住函数,如下所示:
template <Function, Handler>
friend bool asio_handler_is_continuation(echo_op<Function, Handler>* handler)
{
using boost::asio::asio_handler_is_continuation;
return handler.p_->step == 1 ||
asio_handler_is_continuation(std::addressof(handler.p_->handler()));
}
Run Code Online (Sandbox Code Playgroud)
的声明内echo_op。
从Boost 1.66开始,上面的代码不太可能有任何效果(没有BOOST_ASIO_NO_DEPRECATION宏)。所以我应该使用defer.
但是,由于boost::asio::async_read_until有保证说:“处理程序的调用将被以某种方式等效进行使用boost ::支持ASIO :: io_context ::后()”,*this将不使用被调用defer,也就是说,作为一个延续。
是否有任何解决方法可以boost::asio::async_read_until使用调用处理程序defer?有没有利用defer函数的好例子?
这在过去也让我感到困惑。
Executor::defer并且Executor::post都执行相同的操作,除了这个注意事项:
注意:虽然对 defer 的要求与 post 相同,但 post 的使用传达了调用者不会阻止 f1 进程的第一步的偏好,而 defer 传达的偏好是调用者确实阻止了 f1 的第一步。defer 的一种用途是传达调用者的意图,即 f1 是当前调用上下文的延续。执行器可以使用此信息来优化或以其他方式调整调用 f1 的方式。——尾注
https://www.boost.org/doc/libs/1_67_0/doc/html/boost_asio/reference/Executor1.html
因此,链接延续的责任似乎已成为Executor模型的实现细节。
据我所知,这意味着您需要做的就是调用 free 函数defer(executor, handler),执行程序将“做正确的事”
找到了一些文档,其中显示了如何通过最终执行程序链接处理程序:
文档来源:https : //github.com/chriskohlhoff/asio-tr2/blob/master/doc/executors.qbk
示例:https : //github.com/chriskohlhoff/executors/blob/v0.2-branch/src/examples/executor/async_op_2.cpp
请参阅 async_op_2.cpp 中的第 38 行以上