asio::use_future 如何与 co_await 一起使用?

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

这是一个简单的

echo
函数,我想为每个
cancellation_signal
创建一个单独的
echo
。我希望
echo
一秒钟后退出,但我需要确保
wait
函数在退出之前完成。我该怎么做?

asio 1.31.0

awaitable<void> wait(asio::cancellation_signal& cs,int timeoutms)
{
    steady_timer tm(co_await this_coro::executor);

    try
    {
        tm.expires_from_now(std::chrono::milliseconds(timeoutms));
        co_await tm.async_wait();
    }
    catch (const std::exception&)
    {
    }

    //cancel
    cs.emit(asio::cancellation_type::partial);
}
awaitable<void> echo(tcp::socket sock)
{
    error_code ec;
    printf("echo begin | %s\n", addr(sock.remote_endpoint(ec)).c_str());

    char buf[0x1000];
    asio::cancellation_signal cs;
    auto task = co_spawn(sock.get_executor(), wait(cs,1000), asio::use_future);

    try
    {
        while (true)
        {
            int n = 0;
            std::tie(ec, n) = co_await sock.async_read_some(buffer(buf), asio::bind_cancellation_slot(cs.slot(), as_tuple(use_awaitable)));
            if(ec){
                printf("echo error | %s | %s\n", addr(sock.remote_endpoint(ec)).c_str(), ec.message().c_str());
                break;
            }
            co_await asio::async_write(sock, buffer(buf,n), use_awaitable);
        }
    }
    catch (const std::exception& e)
    {
        printf("echo error | %s | %s\n", addr(sock.remote_endpoint(ec)).c_str(), e.what());
    }

    //TODO This won't work.
    co_await task;

    printf("echo end   | %s\n", addr(sock.remote_endpoint(ec)).c_str());
}

我尝试过这个方法,但没有成功。

auto task = co_spawn(sock.get_executor(), wait(cs,1000), asio::use_awaitable);
...

co_await std::move(task);
boost-asio
1个回答
0
投票

你不能。 Future 本质上是阻塞的,这与协程挂起不兼容。

在最近的 Asio 版本中,您可以使用实验性

asio::use_promise
https://www.boost.org/doc/libs/1_86_0/doc/html/boost_asio/reference/experimental__use_promise.html

这将允许您等待操作结果。或者,使用

asio::deferred
,因为这似乎正是您所需要的:等待延迟的操作。

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