(重新)调用协程和等待协程之间有什么区别?

时间:2020-11-01 20:21:54

标签: coroutine c++20 c++-coroutine

我进入协同例程迟到了;但是现在C ++ 20已经有了它们,可以这么说。具体来说,我在Timur Doumler的this CppCon20 talk中观看了有关协程的片段。

Timur首先说明如何使用带有函数和协程(或协程和相关的生成器)的协程:

my_generator<int> f() {
 int i = 0;
 while (true)
   co_yield i++;
}

void foo() {
  auto g = f();
  std::cout << g() << '\n';
  std::cout << g() << '\n';
  std::cout << g() << '\n';
}

稍后,他在该细分受众群中介绍co_await,例如:

async_generator<T> f1() { 
  // code
  auto u = co_await f2();
  // more code
  co_return u;
}

async_generator<U> f2() {
  // code
  co_yield u;
}

现在,我不明白的是,第二个示例与仅调用第一个示例中的协程不同,例如:

async_generator<T> f1() {
  auto g2 = f2();
  // code
  auto u = g2();
  // more code
  co_return u;
}

async_generator<U> f2() {
  // code
  co_yield u;
}

我尝试寻找co_await on cppreference,并且确实存在,但是-它链接到一般的coroutines page-老实说,我从树上看不见森林。我宁愿不知道所有细节-现在。我只想了解高层的概念差异。

1 个答案:

答案 0 :(得分:1)

co_yield语句仅在存在暂停上下文时才有意义。生成器的悬浮上下文的一个示例是在循环内使用co_yield(为某些条件提供值)。

在此示例中:

async_generator<T> f1() { 
  // code
  auto u = co_await f2();
  // more code
  co_return u;
}

async_generator<U> f2() {
  // code
  co_yield u;
}

co_yeild不与任何暂停上下文相关联,因此它将作为典型函数起作用(即co_yield被解释为正常的return语句)。 auto u将等到f2到达函数末尾,从而使执行工作成为典型的函数调用语义。

在此示例中:

async_generator<T> f1() {
  auto g2 = f2();
  // code
  auto u = g2();
  // more code
  co_return u;
}

async_generator<U> f2() {
  // code
  co_yield u;
}

同样,由于缺少 promise对象的创建和操作,因此缺少了悬浮上下文。因此,该代码将与前面的示例完全相同。

但是,如果示例在暂停上下文方面有所不同,则co_yield的工作方式可能有所不同。

here找到了关于协程与诺言对象之间相互作用的权威解释(使用co_await和co_yield)。