gpt4 book ai didi

c++ - C++20 中的协程是什么?

转载 作者:IT老高 更新时间:2023-10-28 12:05:46 28 4
gpt4 key购买 nike

什么是协程 ?

它在哪些方面与“Parallelism2”或/和“Concurrency2”不同(查看下图)?

下图来自 ISOCPP。

https://isocpp.org/files/img/wg21-timeline-2017-03.png

enter image description here

最佳答案

在抽象层面上,协程将拥有执行状态的想法与拥有执行线程的想法分开。
SIMD(单指令多数据)有多个“执行线程”但只有一个执行状态(它只适用于多个数据)。可以说并行算法有点像这样,因为你有一个“程序”在不同的数据上运行。
线程有多个“执行线程”和多个执行状态。你有不止一个程序,不止一个执行线程。
协程有多个执行状态,但不拥有一个执行线程。你有一个程序,程序有状态,但它没有执行线程。

协程最简单的例子是来自其他语言的生成器或枚举。
在伪代码中:

function Generator() {
for (i = 0 to 100)
produce i
}
Generator被调用,第一次调用返回 0 .它的状态被记住(多少状态随着协程的实现而变化),下次你调用它时它会从上次中断的地方继续。所以下次它返回1。然后 2。
最后到达循环的末尾,从函数的末尾掉下来;协程完成。 (这里发生的事情因我们所谈论的语言而异;在 python 中,它会引发异常)。
协程为 C++ 带来了这种能力。
有两种协程;堆叠和无堆叠。
无堆栈协程仅在其状态和执行位置中存储局部变量。
堆栈式协程存储整个堆栈(如线程)。
无堆栈协程可以非常轻量级。我读到的最后一个提案基本上涉及将您的函数重写为有点像 lambda 的东西;所有局部变量都进入对象的状态,标签用于跳转到/从协程“产生”中间结果的位置。
产生值的过程称为“产量”,因为协程有点像协作多线程;您将执行点交还给调用者。
Boost 有一个堆栈协程的实现;它可以让你调用一个函数来为你让步。 Stackful 协程更强大,但也更昂贵。

协程不仅仅是一个简单的生成器。您可以在协程中等待协程,这使您可以以有用的方式组合协程。
协程,如 if、循环和函数调用,是另一种“结构化转到”,它可以让您以更自然的方式表达某些有用的模式(如状态机)。

Coroutines在C++中的具体实现有点意思。
在最基本的层面上,它为 C++ 添加了几个关键字: co_return co_await co_yield ,以及与它们一起使用的一些库类型。
一个函数通过在其主体中包含一个协程而成为协程。因此,从它们的声明来看,它们与函数没有区别。
当在函数体中使用这三个关键字之一时,会发生一些标准的对返回类型和参数的强制检查,并将函数转换为协程。这种检查告诉编译器在函数挂起时将函数状态存储在哪里。
最简单的协程是一个生成器:
generator<int> get_integers( int start=0, int step=1 ) {
for (int current=start; true; current+= step)
co_yield current;
}
co_yield暂停函数执行,将该状态存储在 generator<int> 中,然后返回 current 的值通过 generator<int> .
您可以遍历返回的整数。 co_await同时让您将一个协程拼接到另一个协程上。如果您在一个协程中并且在继续之前需要等待事物(通常是协程)的结果,您 co_await就可以了。如果他们准备好了,你就立即进行;如果没有,您将暂停,直到您正在等待的等待对象准备就绪。
std::future<std::expected<std::string>> load_data( std::string resource )
{
auto handle = co_await open_resouce(resource);
while( auto line = co_await read_line(handle)) {
if (std::optional<std::string> r = parse_data_from_line( line ))
co_return *r;
}
co_return std::unexpected( resource_lacks_data(resource) );
}
load_data是一个生成 std::future 的协程当命名资源被打开并且我们设法解析到我们找到所请求数据的点时。 open_resourceread_line s 可能是打开文件并从中读取行的异步协程。 co_await连接 load_data的挂起和就绪状态他们的进步。
C++ 协程比这更灵活,因为它们是作为用户空间类型之上的最小语言功能集实现的。用户空间类型有效地定义了 co_return co_awaitco_yield意思是——我见过人们用它来实现一元可选表达式,例如 co_await在空的可选项上自动将空状态传播到外部可选项:
modified_optional<int> add( modified_optional<int> a, modified_optional<int> b ) {
co_return (co_await a) + (co_await b);
}
而不是
std::optional<int> add( std::optional<int> a, std::optional<int> b ) {
if (!a) return std::nullopt;
if (!b) return std::nullopt;
return *a + *b;
}

关于c++ - C++20 中的协程是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43503656/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com