c++ - 如何在组合函数中使用 boost::asio::defer()?

标签 c++ boost boost-asio boost-beast

在 Boost 1.66 上,Asio 有 deprecated asio_handler_is_continuation钩子(Hook)函数, boost defer的使用功能。 It seems that defer函数的行为与 post 完全相同当 asio_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);
    })

现在 async_read_until完成后,传递的 lambda 处理程序将使用某种等同于 boost::asio::post 的方式被调用。 .但是async_write lambda 处理程序内部是上一个异步任务的延续,所以我想使用 defer 调用 lambda 处理程序采取优化的冒险。

有什么办法可以用defer (而不是 post )来调用上面示例中的 lambda 处理程序?

原始帖子:我正在尝试编写一个简单的启动函数 async_echo类似于 beast document 中的那个, 除了调用 boost::asio::async_write 的部分将被称为延续。为此,事先进行中间操作boost::asio::async_read_until必须调用处理程序 *this作为延续。

这是我在 beast 文档的 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;
}

在 1.66 之前的日子里,我可以简单地 hook 函数如下:

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()));
}

echo_op 的声明中.

从 Boost 1.66 开始,上面的代码不太可能有任何效果(没有 BOOST_ASIO_NO_DEPRECATION 宏)。所以我应该使用 defer .

但是自boost::asio::async_read_untila guarantee “处理程序的调用将以等同于使用 boost::asio::io_context::post() 的方式执行。”,*this不会使用 defer 调用, 即作为延续。

是否有任何解决方法使 boost::asio::async_read_until使用 defer 调用处理程序?有没有利用 defer 的好例子?功能?

最佳答案

这在过去也让我感到困惑。

Executor::deferExecutor::post 都执行相同的操作,除了这个注释:

Note: Although the requirements placed on defer are identical to post, the use of post conveys a preference that the caller does not block the first step of f1's progress, whereas defer conveys a preference that the caller does block the first step of f1. One use of defer is to convey the intention of the caller that f1 is a continuation of the current call context. The executor may use this information to optimize or otherwise adjust the way in which f1 is invoked. —end note

https://www.boost.org/doc/libs/1_67_0/doc/html/boost_asio/reference/Executor1.html

因此,链接延续的责任似乎已成为 Executor 模型的实现细节。

据我所知,这意味着您需要做的就是调用自由函数 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+ 行

关于c++ - 如何在组合函数中使用 boost::asio::defer()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50176602/

相关文章:

c++ - boost::asio - 服务器之间的冲突,双向通信

c++ - boost_asio_handler_invoke_helpers::invoke 是否仍然是在 boost asio 1.70 中调用完成处理程序的受支持方式?

c++ - 按属性对特征向量进行多排序的数据结构

c++ - 从访问者更改 boost::variant 基础类型

c++ - Cuda - 从设备全局内存复制到纹理内存

c++ - boost 日志 severity_logger init_from_stream

c++ - BOOST_STATIC_ASSERT 的命名空间范围

c++ - boost 中的协程局部变量

c++ - 如何简化这个二叉树遍历函数?

c++ - 如何使用 C++ 从 png 文件中提取像素?