与 C++20 协程一起使用时,boost::asio::use_awaitable 和 boost::asio::deferred 有什么区别?

问题描述 投票:0回答:1

将 C++20 协程与 Boost.Asio 结合使用时,可以使用

boost::asio::use_awaitable
boost::asio::deferred
使操作等待,如以下示例所示。

std::size_t n = co_await my_socket.async_read_some(buffer, use_awaitable);
std::size_t n = co_await my_socket.async_read_some(buffer, deferred);

有什么区别?在什么情况下您会使用其中一种而不是另一种?

c++ boost c++20 boost-asio c++-coroutine
1个回答
0
投票

Deferred 与协程无关。它将任何异步启动打包到新的启动函数中,该函数可以接受任何完成令牌。 文档中显示了延迟启动的玩具实现示例。

更明确的使用方式是拼写:

auto d = co_await my_socket.async_read_some(buffer, deferred);
std::size_t n = co_await d(asio::use_awaitable);

我承认我不知道 Asio 的可等待框架(

promise_type
)为异步操作实现了
await_transform
,但是它确实,这就是简写的原因

std::size_t n = co_await d;

有效。

其他注意事项:

  • Deferred 可以与不同的完成令牌一起使用,例如定期回调或

    use_future

  • 延迟的异步操作是可复制的

  • 直到几个版本之前,延迟异步操作都是可重用的,所以

    n = co_await d;
    n = co_await d;
    

    会起作用的。在我下面的测试中,我发现这最近发生了变化,所以你需要

    auto d2 = d;
    n = co_await std::move(d);
    n = co_await std::move(d2);
    

达到同样的效果。

以下代码演示了其中一些概念的实际应用:

实时编译器资源管理器

#include <any>
#include <iostream>
#include <mutex>
#include <sstream>
#include <string>
#include <thread>
#include <vector>
#include <boost/asio.hpp>
namespace asio = boost::asio;
using asio::ip::tcp;
using boost::system::error_code;

asio::awaitable<void> foo() try {
    tcp::socket my_socket{co_await asio::this_coro::executor};
    co_await my_socket.async_connect({{}, 7878}, asio::use_awaitable);

    std::array<char, 16> b;
    {
        asio::awaitable<size_t> aw = my_socket.async_read_some(asio::buffer(b), asio::use_awaitable);
        size_t                  n  = co_await std::move(aw);
        std::cout << __LINE__ << ": Read: " << n << " bytes" << std::endl;
    }
    {
        /*asio::deferred_async_operation<void(error_code, size_t), tcp::socket::initiate_async_receive,
                                       asio::mutable_buffers_1 const&, int>*/
        auto d1 = my_socket.async_read_some(asio::buffer(b), asio::deferred);
        auto d2 = d1;

        size_t n = co_await d1(asio::use_awaitable);
        std::cout << __LINE__ << ": Read: " << n << " bytes" << std::endl;

        n = co_await std::move(d2);
        std::cout << __LINE__ << ": Read: " << n << " bytes" << std::endl;
    }
} catch(boost::system::system_error const& se) {
        std::cout << __LINE__ << ": " << se.code().message() << std::endl;
}

int main() {
    asio::io_context ioc;
    co_spawn(ioc, foo, asio::detached);
    ioc.run();
}

演示输出:

© www.soinside.com 2019 - 2024. All rights reserved.