gpt4 book ai didi

c++ - boost::coroutine2 与 CoroutineTS

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:36:25 24 4
gpt4 key购买 nike

Boost::Coroutine2 和 CoroutineTS(C++20) 是 C++ 中流行的协程实现。两者都会挂起和恢复,但两种实现遵循完全不同的方法。

协程TS(C++20)

  • 无堆栈
  • 返回暂停
  • 使用特殊关键字
generator<int> Generate()
{
co_yield;
});

boost::coroutine2

  • 堆叠
  • 通过电话暂停
  • 不要使用特殊关键字
pull_type source([](push_type& sink)
{
sink();
});

有没有我应该只选择其中一个的特定用例?

最佳答案

主要的技术区别在于您是否希望能够从嵌套调用中退出。这不能使用无堆栈协程来完成。

另一件需要考虑的事情是,stackful coroutines 有自己的堆栈和上下文(例如信号掩码、堆栈指针、CPU 寄存器等),因此它们比 stackless coroutines 有更大的内存占用。这可能是一个问题,尤其是当您的系统资源受限或同时存在大量协程时。

我不知道它们在现实世界中如何比较性能,但总的来说,无堆栈协程更高效,因为它们的开销更少(无堆栈任务切换不必交换堆栈、存储/加载寄存器,以及恢复信号掩码等)。

有关最小无堆栈协程实现的示例,请参阅 Simon Tatham's coroutines使用 Duff's Device .很直观的是,它们非常高效。

此外,this question有很好的答案,更详细地介绍了堆栈协程和无堆栈协程之间的区别。

如何从无堆栈协程中的嵌套调用中退出?尽管我说这是不可能的,但这并不是 100% 正确:您可以使用(至少两个)技巧来实现这一点,每个技巧都有一些缺点:首先,您必须将每个应该能够产生调用协程的调用也转换为协程。现在,有两种方法:

  1. 蹦床方法:您只需在循环中从父协程调用子协程,直到它返回。每次你通知子协程,如果它没有完成,你也会让出调用协程。请注意,这种方法禁止直接调用子协程,您总是必须调用最外层的协程,然后它必须重新进入整个调用堆栈。对于 n 的嵌套深度,这具有 O(n) 的调用和返回复杂度。如果您正在等待一个事件,该事件只需通知最外层的协程即可。

  2. 父链接方法:您将父协程地址传递给子协程,让出父协程,子协程在完成后手动恢复父协程。请注意,此方法禁止直接调用除最内层协程之外的任何协程。此方法的调用和返回复杂度为 O(1),因此通常更可取。缺点是你必须在某个地方手动注册最内层协程,以便下一个想要恢复外层协程的事件知道直接针对哪个内层协程。

注意:调用和返回复杂度是指通知协程恢复时所采取的步骤数,以及通知协程返回后所采取的步骤数再次调用通知程序。

关于c++ - boost::coroutine2 与 CoroutineTS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55078177/

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