c++20 中的协程是什么?
它与“Parallelism2”或/和“Concurrency2”有什么不同(看下图)?
下图来自 ISOCPP。
https://isocpp.org/files/img/wg21-timeline-2017-03.png
原文由 Pavan Chandaka 发布,翻译遵循 CC BY-SA 4.0 许可协议
c++20 中的协程是什么?
它与“Parallelism2”或/和“Concurrency2”有什么不同(看下图)?
下图来自 ISOCPP。
https://isocpp.org/files/img/wg21-timeline-2017-03.png
原文由 Pavan Chandaka 发布,翻译遵循 CC BY-SA 4.0 许可协议
协程应该是(在 C++ 中)能够“等待”其他例程完成并为暂停、暂停、等待的例程继续执行所需的任何功能的函数。 C++ 人最感兴趣的特性是协程理想情况下不占用堆栈空间……C# 已经可以使用 await 和 yield 执行类似的操作,但 C++ 可能必须重新构建才能使用。
并发主要关注关注点的分离,其中关注点是程序应该完成的任务。这种关注点的分离可以通过多种方式实现……通常是某种委托。并发的想法是许多进程可以独立运行(关注点分离),并且“侦听器”会将这些分离的关注点产生的任何内容引导到它应该去的任何地方。这在很大程度上依赖于某种异步管理。有许多并发方法,包括面向方面的编程和其他方法。 C# 有’delegate’ 操作符,它工作得很好。
并行听起来像并发,可能会涉及,但实际上是一种物理构造,涉及许多处理器,这些处理器或多或少地以并行方式排列,软件能够将部分代码引导到将运行它的不同处理器并接收结果同步。
原文由 Dr t 发布,翻译遵循 CC BY-SA 3.0 许可协议
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答2.7k 阅读✓ 已解决
3 回答3.4k 阅读
1 回答3.3k 阅读
在抽象层面上,协程将拥有执行状态的想法与拥有执行线程的想法分开。
SIMD(单指令多数据)有多个“执行线程”,但只有一个执行状态(它只适用于多个数据)。可以说并行算法有点像这样,因为你有一个“程序”在不同的数据上运行。
线程有多个“执行线程”和多个执行状态。你有不止一个程序和不止一个执行线程。
协程有多种执行状态,但不拥有执行线程。你有一个程序,程序有状态,但它没有执行线程。
协程最简单的例子是其他语言的生成器或枚举。
在伪代码中:
Generator
被调用,第一次调用它返回0
。它的状态被记住(有多少状态随协同程序的实现而变化),下次调用它时,它会从中断的地方继续。所以它下次返回 1。然后2。最后它到达循环的末尾并从函数的末尾掉下来;协程完成。 (这里发生的事情因我们所谈论的语言而异;在 python 中,它会引发异常)。
协程为 C++ 带来了这种能力。
有两种协程;堆叠和无堆叠。
无堆栈协程仅在其状态和执行位置中存储局部变量。
堆栈式协程存储整个堆栈(如线程)。
无堆栈协程可以非常轻量级。我读到的最后一个建议基本上是把你的函数重写成有点像 lambda 的东西。所有局部变量都进入对象的状态,标签用于跳转到协程“产生”中间结果的位置/从该位置跳转。
产生值的过程称为“yield”,因为协程有点像协作多线程;您正在将执行点交还给调用者。
Boost 有一个堆栈协程的实现;它可以让你调用一个函数来为你让步。堆栈式协程更强大,但也更昂贵。
协程不仅仅是一个简单的生成器。您可以在协程中等待一个协程,这可以让您以一种有用的方式组合协程。
协程,如 if、循环和函数调用,是另一种“结构化 goto”,可以让您以更自然的方式表达某些有用的模式(如状态机)。
C++中Coroutines的具体实现有点意思。
在最基本的层面上,它为 C++ 添加了一些关键字:
co_return
co_await
co_yield
以及一些可以使用它们的库类型。一个函数通过在其主体中包含其中一个而成为协程。因此,从他们的声明来看,它们与函数没有区别。
当在函数体中使用这三个关键字之一时,会发生一些标准强制检查返回类型和参数,并将函数转换为协程。这种检查告诉编译器在函数挂起时将函数状态存储在哪里。
最简单的协程是生成器:
co_yield
suspends the functions execution, stores that state in thegenerator<int>
, then returns the value ofcurrent
through thegenerator<int>
.您可以遍历返回的整数。
co_await
同时让您可以将一个协程拼接到另一个协程上。如果您在一个协程中并且在继续之前需要等待的结果(通常是协程),那么您co_await
就可以了。如果他们准备好了,您立即进行;如果没有,您将暂停,直到您等待的可等待对象准备好。load_data
是一个协程,当命名资源打开并且我们设法解析到我们找到请求的数据的点时,它会生成一个std::future
。open_resource
和read_line
可能是打开文件并从中读取行的异步协程。co_await
将load_data
的挂起和就绪状态连接到它们的进度。C++ 协程比这更灵活,因为它们是作为用户空间类型之上的最小语言特性集实现的。用户空间类型有效地定义了
co_return
co_await
和co_yield
意味着 什么co_await
我见过人们用它来实现单子可选表达式,例如---
在空选项上自动将空状态传播到外部选项:代替