Nis*_*han 6 c++ boost coroutine boost-coroutine2
Boost :: Coroutine2和CoroutineTS(C ++ 20)是C ++中流行的协程实现。两者都暂停和恢复,但是两种实现遵循完全不同的方法。
协程TS(C ++ 20)
generator<int> Generate()
{
co_yield;
});
Run Code Online (Sandbox Code Playgroud)
boost ::协程2
pull_type source([](push_type& sink)
{
sink();
});
Run Code Online (Sandbox Code Playgroud)
是否有任何我只应选择其中一种的特定用例?
主要的技术区别是您是否希望能够从嵌套调用中产生。使用无堆栈协程无法做到这一点。
另一件要考虑的事情是,堆栈式协程有自己的堆栈和上下文(例如信号掩码、堆栈指针、CPU 寄存器等),因此它们比无堆栈式协程具有更大的内存占用。这可能是一个问题,特别是如果您有一个资源受限的系统或同时存在大量协程。
我不知道它们在现实世界中如何比较性能,但总的来说,无堆栈协程更有效,因为它们的开销较小(无堆栈任务切换不必交换堆栈、存储/加载寄存器和恢复信号面具等)。
有关最小无堆栈协程实现的示例,请参阅Simon Tatham 的协程使用Duff 的 Device。非常直观的是,它们尽可能高效。
此外,这个问题有很好的答案,更详细地介绍了有栈和无栈协程之间的区别。
如何从无堆栈协程中的嵌套调用中产生? 尽管我说这是不可能的,但这并不是 100% 正确:您可以使用(至少两个)技巧来实现这一点,每个技巧都有一些缺点:首先,您必须转换每个应该能够产生您的调用协程的调用也进入协程。现在,有两种方法:
在蹦床方式:您只需拨打从父协程孩子协程在一个循环,直到它返回。每次通知子协程,如果它没有完成,你也会让调用协程。请注意,这种方法禁止直接调用子协程,您总是必须调用最外层的协程,然后必须重新进入整个调用堆栈。对于嵌套深度n ,这具有O(n)的调用和返回复杂度。如果您正在等待一个事件,则该事件只需通知最外层的协程即可。
在父链接方式:您通过父协程地址给孩子协程,产生母体协程,而孩子协程手动恢复父协同程序,一旦它完成。请注意,此方法禁止直接调用除最内层协程之外的任何协程。这种方法的调用和返回复杂度为O(1),因此通常更可取。缺点是你必须在某处手动注册最内层协程,以便下一个想要恢复外层协程的事件知道直接针对哪个内层协程。
注意:调用和返回复杂度是指通知协程恢复它时所采取的步骤数,以及通知它再次返回调用通知程序后所采取的步骤数。
| 归档时间: |
|
| 查看次数: |
449 次 |
| 最近记录: |