如何调用C++程序中的第一个(顶级)协程?

Vit*_*lii 2 c++ c++20 c++-coroutine

我们不能co_await来自非协程,所以,我们不能做这样的事情:

void main(void)
{
  co_await my_coroutine();
}
Run Code Online (Sandbox Code Playgroud)

假设这my_coroutine是我们无法直接控制并且无法创建其基于回调的版本。那么到底如何调用它呢?

天真的想法是这样的:

void main(void)
{
  my_coroutine();
}
Run Code Online (Sandbox Code Playgroud)

当然这是行不通的,因为我们会在完成main之前退出。my_coroutine

那么该怎么办?一种可行的想法如下所示:

void main(void)
{
  auto my_promise = my_coroutine();
  bool my_promise_finished = false;
  while(!my_promise_finished)
  {
    /* somehow detect indirectly/in undocumented way that my_coroutine finished */
    my_promise_finished = is_my_promised_finished();
    Sleep(1000);
  }
}
Run Code Online (Sandbox Code Playgroud)

这个想法很丑陋。1. 我们必须使用无文档/不可靠的方式来检测协程是否完成。2. 我们阻塞整个主线程等待,而另一个线程将执行某些操作。

是否有任何好的/官方方法如何调用 C++ 程序中的第一个/顶级协程并等待其完成,而不阻塞该作业的整个线程。

这个例子足够实用了。例如,我们可能有一个 URL 下载实用程序,它调用单个顶级协程download_1000_urls,它可能会自己创建多个线程并从 Internet 下载大量数据;它仍然是单个顶级协程,main必须以某种方式调用,类似于旧式异步Application.Run方法。

Nic*_*las 6

虽然 C++20 协程功能确实实现了“协程”,但它们与您在其他语言中看到的“协程”不同。我的意思是,它们是,但不是你想的那样。

对于这个问题,最重要的是:协程是函数如何工作的实现细节。

my_coroutine任何不在.my_coroutine这只是一个函数。与任何其他函数一样,它需要一定数量的参数,执行某些操作,并向调用者提供某种返回值。

因此,如果一个函数是一个协程,并且该协程想要将一些延迟值或控制机制传递给其调用者,那么它拥有的唯一接口就是函数的返回值。这就是外部代码与协程交互的方式。如果返回值允许,它可以提供一种机制来检查它是否完成,如果没有完成则继续协程。它可以提供一种机制来请求生成器式协程的下一个值。它可以做很多事情

但在所有这些情况下,都由协程本身来提供这些接口。对于如何“控制协程”,没有一刀切的答案。在一个真实的例子中,my_coroutine将返回一些对象,并且该对象的成员是您的控制机制。无论它提供什么接口,你都可以控制它。

因此,如果my_coroutine是某个多步骤过程,并且my_coroutine期望它的调用者告诉它执行下一步,那么my_coroutine需要返回一个有助于此操作的对象。或者,如果my_coroutine将自身注册到某个异步设施,一旦它正在等待的进程完成,该设施就会自动恢复它,那么 的my_coroutine返回值将无法执行下一步,因为那是其他人的工作。

特定函数提供的界面告诉您如何与其交互。没有统一的接口,因为有数十种方法可以使用可以暂停和恢复的功能。您构建特定用例所需的界面。