ASIO C++协程取消

ASIO C++ coroutine cancellation

我正在生成一个协程,如下所示。

asio::co_spawn(executor, my_coro(), asio::detached);

我该如何取消它?

据我所知,可以通过将处理程序与 asio::bind_cancellation_slot 绑定来简单地实现每个处理程序的取消。这在我的具体示例中不起作用(无论使用 asio::detached“处理程序”或某些 lambda),而且它不起作用对我来说很有意义。

我发现 this blog post 基本上是说从另一个协程生成协程并等待它(使用适当的 asio::bind_cancellation_slot 设置)就可以了。这对我来说失败了,因为在下面的例子中 my_coro 似乎从来没有 运行。此外,我什至不知道为什么这会起作用(关于取消)。

asio::awaitable<void> cancelable(asio::cancellation_signal& sig, asio::awaitable<void>&& awaitable) {
    co_await asio::co_spawn(co_await asio::this_coro::executor, std::move(awaitable), asio::bind_cancellation_slot(sig.slot(), asio::use_awaitable));
    co_return;
}

// ...

asio::cancellation_signal signal;
asio::co_spawn(executor, cancelable(signal, my_coro()), asio::detached);

在ASIO中将asio::cancellation_signal连接到协程(由co_await asio::this_coro::cancellation_state获得)的asio::cancellation_state的正确方法是什么?

如果有帮助:我在最新的 master 上使用独立的 ASIO,即不是 boost 版本。

要在 asio 中取消协程,请使用新的 awaitable_operator '||'。可等待的运算符“||”允许 co_await 多个协程,直到其中一个协程完成。例如:

#include "boost/asio/experimental/awaitable_operators.hpp"
#include <boost/asio.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/system_timer.hpp>
#include <boost/asio/this_coro.hpp>
#include <chrono>
#include <iostream>

boost::asio::awaitable<void>
printHelloEverySecond ()
{
  for (;;)
    {
      std::cout << "Hello" << std::endl;
      boost::asio::system_timer timer{ co_await boost::asio::this_coro::executor };
      timer.expires_after (std::chrono::seconds{ 1 });
      co_await timer.async_wait (boost::asio::use_awaitable);
    }
}

boost::asio::awaitable<void>
stopAfter4500Milliseconds (boost::asio::system_timer &timer)
{
  boost::asio::system_timer stopAfterFiveSeconds{ co_await boost::asio::this_coro::executor };
  stopAfterFiveSeconds.expires_after (std::chrono::milliseconds{ 4500 });
  co_await stopAfterFiveSeconds.async_wait (boost::asio::use_awaitable);
  timer.cancel ();
}

boost::asio::awaitable<void>
cancel (boost::asio::system_timer &timer)
{
  try
    {
      co_await timer.async_wait (boost::asio::use_awaitable);
    }
  catch (boost::system::system_error &e)
    {
      using namespace boost::system::errc;
      if (operation_canceled == e.code ())
        {
          //  swallow cancel
        }
      else
        {
          std::cout << "error in timer boost::system::errc: " << e.code () << std::endl;
          abort ();
        }
    }
}

int
main ()
{
  boost::asio::io_context ioContext{};
  boost::asio::system_timer timer{ ioContext };
  timer.expires_at (std::chrono::system_clock::time_point::max ());
  using namespace boost::asio::experimental::awaitable_operators;
  co_spawn (ioContext, printHelloEverySecond () || cancel (timer), [] (auto, auto) { std::cout << "stopped" << std::endl; });
  co_spawn (ioContext, stopAfter4500Milliseconds (timer), boost::asio::detached);
  ioContext.run ();
}

此处“printHelloEverySecond ()”将运行 直到“cancel()”returns 成功,这发生在定时器在 4500 毫秒后取消(在“stopAfter4500Milliseconds”中)。这允许在计时器被取消时取消“printHelloEverySecond ()”。 供参考:
Chris Kohlhoff explains awaitable_operator and cancelation