你如何在 C++ 中实现协程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/121757/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you implement Coroutines in C++
提问by Mike Elkins
I doubt it can be done portably, but are there any solutions out there? I think it could be done by creating an alternate stack and reseting SP,BP, and IP on function entry, and having yield save IP and restore SP+BP. Destructors and exception safety seem tricky but solvable.
我怀疑它是否可以便携地完成,但是有什么解决方案吗?我认为可以通过创建备用堆栈并在函数入口处重置 SP、BP 和 IP,并让 yield save IP 并恢复 SP+BP 来完成。析构函数和异常安全看起来很棘手但可以解决。
Has it been done? Is it impossible?
已经完成了吗?不可能吗?
回答by Ted
Yes it can be donewithout a problem. All you need is a little assembly code to move the call stack to a newly allocated stack on the heap.
是的,它可以毫无问题地完成。您所需要的只是一些汇编代码,将调用堆栈移动到堆上新分配的堆栈。
I would look at the boost::coroutinelibrary.
我会看看boost::coroutine库。
The one thing that you should watch out for is a stack overflow. On most operating systems overflowing the stack will cause a segfault because virtual memory page is not mapped. However if you allocate the stack on the heap you don't get any guarantee. Just keep that in mind.
您应该注意的一件事是堆栈溢出。在大多数操作系统上,堆栈溢出会导致段错误,因为虚拟内存页面未映射。但是,如果您在堆上分配堆栈,则无法得到任何保证。要时刻铭记在心。
回答by zvrba
On POSIX, you can use makecontext()/swapcontext() routines to portably switch execution contexts. On Windows, you can use the fiber API. Otherwise, all you need is a bit of glue assembly code that switches the machine context. I have implemented coroutines both with ASM (for AMD64) and with swapcontext(); neither is very hard.
在 POSIX 上,您可以使用 makecontext()/swapcontext() 例程来可移植地切换执行上下文。在 Windows 上,您可以使用光纤 API。否则,您所需要的只是一些用于切换机器上下文的胶水汇编代码。我已经使用 ASM(用于 AMD64)和 swapcontext() 实现了协程;两者都不是很难。
回答by tgoodhart
For posterity,
为后人,
Dmitry Vyukov's wondeful web sitehas a clever trick using ucontext and setjump to simulated coroutines in c++.
Dmitry Vyukov 的精彩网站有一个巧妙的技巧,它使用 ucontext 和 setjump 来模拟 C++ 中的协程。
Also, Oliver Kowalke's context library was recently acceptedinto Boost, so hopefully we'll be seeing an updated version of boost.coroutine that works on x86_64 soon.
此外,Oliver Kowalke 的上下文库最近被Boost接受,所以希望我们很快就会看到更新版本的 boost.coroutine 可以在 x86_64 上运行。
回答by Eonil
There's no easy way to implement coroutine. Because coroutine itself is out of C/C++'s stack abstraction just like thread. So it cannot be supported without language level changes to support.
没有简单的方法来实现协程。因为协程本身就像线程一样脱离了 C/C++ 的堆栈抽象。因此,如果没有语言级别的更改支持,则无法支持它。
Currently(C++11), all existing C++ coroutine implementations are all based on assembly level hacking which is hard to be safe and reliable crossing over platforms. To be reliable it needs to be standard, and handled by compilers rather than hacking.
目前(C++11),所有现有的C++协程实现都是基于汇编级hacking,跨平台难以安全可靠。为了可靠,它需要是标准的,并且由编译器而不是黑客来处理。
There's a standard proposal - N3708for this. Check it out if you're interested.
为此,有一个标准建议 - N3708。如果您有兴趣,请检查一下。
回答by Steve g
You might be better off with an iterator than a coroutine if possible. That way you can keep calling next()
to get the next value, but you can keep your state as member variables instead of local variables.
如果可能的话,使用迭代器可能比使用协程更好。这样,您可以继续调用next()
以获取下一个值,但您可以将状态保留为成员变量而不是局部变量。
It might make things more maintainable. Another C++ developer might not immediately understand the coroutine whereas they might be more familiar with an iterator.
它可能会使事情更易于维护。另一位 C++ 开发人员可能不会立即理解协程,但他们可能更熟悉迭代器。
回答by Atifm
For those who want to know how they may leverage Coroutines in a portable way in C++ y?o?u? ?w?i?l?l? ?h?a?v?e? ?t?o? ?w?a?i?t? ?f?o?r? ?C?+?+?1?7? the wait is over (see below)! The standards committee is working on the feature see the N3722 paper. To summarize the current draft of the paper, instead of Async and Await, the keywords will be resumable, and await.
对于那些想知道如何在 C++ 中以可移植的方式利用协程的人??将要??有??到??等待??为了??C?+?+?1?7? 等待结束(见下文)!标准委员会正在研究该功能,请参阅N3722 论文。总结一下当前的论文草稿,而不是 Async 和 Await,关键字将是可恢复的和等待。
Take a look at the experimental implementation in Visual Studio 2015 to play with Microsoft's experimental implementation. It doesn't look like clang has a implementation yet.
查看 Visual Studio 2015 中的实验性实现,以玩转 Microsoft 的实验性实现。看起来 clang 还没有实现。
There is a good talk from Cppcon Coroutines a negative overhead abstractionoutline the benefits of using Coroutines in C++ and how it affects simplicity and performance of the code.
Cppcon Coroutines有一个很好的演讲,一个负面的开销抽象概述了在 C++ 中使用协程的好处以及它如何影响代码的简单性和性能。
At present we still have to use library implementations, but in the near future, we will have coroutines as a core C++ feature.
目前我们仍然必须使用库实现,但在不久的将来,我们将把协程作为核心 C++ 特性。
Update: Looks like the coroutine implementation is slated for C++20, but was released as a technical specification with C++17 (p0057r2). Visual C++, clang and gcc allow you to opt in using a compile time flag.
更新:看起来协程实现是为 C++20 设计的,但作为技术规范与 C++17 ( p0057r2) 一起发布。Visual C++、clang 和 gcc 允许您选择使用编译时标志。
回答by yrp
I dont think there are many full-blown, clean implementations in C++. One try that I like is Adam Dunkels' protothread library.
我认为 C++ 中没有很多成熟的、干净的实现。我喜欢的一种尝试是Adam Dunkels 的 protothread 库。
See also Protothreads: simplifying event-driven programming of memory-constrained embedded systemsin the ACM Digital Library and discussion in Wikipedia topic Protothread,
另请参阅Protothreads:简化ACM 数字图书馆中内存受限嵌入式系统的事件驱动编程和维基百科主题Protothread 中的讨论,
回答by Dan
Does COROUTINE a portable C++ library for coroutine sequencingpoint you in the right direction? It seems like an elegant solution that has lasted the test of time.....it's 9 years old!
COROUTINE 用于协程排序的便携式 C++ 库是否为您指明了正确的方向?这似乎是一个经得起时间考验的优雅解决方案......它已经9岁了!
In the DOC folder is a pdf of the paper A Portable C++ Library for Coroutine Sequencing by Keld Helsgaun which describes the library and provides short examples using it.
DOC 文件夹中是 Keld Helsgaun 撰写的 A Portable C++ Library for Coroutine Sequencing 论文的 pdf,其中描述了该库并提供了使用它的简短示例。
[update] I'm actually making successful use of it myself. Curiosity got the better of me, so I looked into this solution, and found it was a good fit for a problem I've been working on for some time!
[更新] 我自己实际上正在成功地使用它。好奇心战胜了我,所以我研究了这个解决方案,发现它非常适合我已经研究了一段时间的问题!
回答by Mark
It is based on (cringe) macros, but the following site provides an easy-to-use generator implementation: http://www.codeproject.com/KB/cpp/cpp_generators.aspx
它基于(畏缩)宏,但以下站点提供了易于使用的生成器实现:http: //www.codeproject.com/KB/cpp/cpp_generators.aspx
回答by Jeff Trull
A new library, Boost.Context, was released today with portable features for implementing coroutines.
今天发布了一个新库Boost.Context,具有用于实现协程的可移植功能。