这是一个简单的
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);
你不能。 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
,因为这似乎正是您所需要的:等待延迟的操作。