【发布时间】:2017-06-13 00:25:52
【问题描述】:
我注意到在 C++ 的 Boost.Coroutine2 中删除了对对称协程的支持,所以我想了解一下——两者之间有什么区别?
【问题讨论】:
标签: coroutine
我注意到在 C++ 的 Boost.Coroutine2 中删除了对对称协程的支持,所以我想了解一下——两者之间有什么区别?
【问题讨论】:
标签: coroutine
Ana Lúcia de Moura 和 Roberto Ierusalimschy 在他们的论文“Revisiting Coroutines”中很好地描述了对称和非对称协程之间的区别:
一个众所周知的协程分类涉及所提供的控制转移操作,并区分了对称和非对称协程的概念。对称协程工具提供了一个单一的控制转移操作,允许协程在它们之间显式地传递控制。非对称协程机制(通常表示为 semi-symmetric 或 semi 协程)提供两种控制转移操作:一种用于调用协程,一种用于挂起协程,后者返回控制到协程调用者。对称协程在同一层次上运行,而不对称协程可以被视为从属于其调用者,它们之间的关系有点类似于被调用例程和调用例程之间的关系。
支持并发编程的协程机制通常提供对称协程来表示独立的执行单元,就像在 Modula-2 中一样。另一方面,旨在实现产生值序列的构造的协程机制通常提供非对称协程。此类构造的示例是 iterators 和 generators。
(省略引文)
在非对称协程模型中,“不对称”是指协程之间存在类似堆栈的调用者-被调用者关系。协程既可以调用另一个协程,也可以通过将控制权交给调用者来挂起自己,通常同时也会给调用者一个值。
在对称协程模型中,协程可以不受限制地将控制权让给任何其他协程。
这两个模型实际上具有相同的表现力;即非对称协程可以使用对称协程来实现,反之亦然。 (参见 Symmetric coroutines,由 Giovanni P. Deretta 编写,关于两种协程之间的转换。)因此,Moura 和 Ierusalimschy 写道:“提供这两种结构只会使 [协程] 机制的语义复杂化,而不会增加它的表现力。”
Coroutine2 的开发者决定不在库中提供对称协程,因为他们认为 boost::context::execution_context(Boost.Context 的一部分)更好地实现对称协程功能:http://lists.boost.org/Archives/boost/2015/06/223701.php
【讨论】:
协程在调用者和被调用者之间切换,例如你进入协程函数,然后切换回调用代码。通常(非对称)协程为此目的有两个功能:
因为你有两个函数来切换上下文,所以称为非对称。 对称协程只有一个功能可以暂停当前上下文并恢复另一个。请注意,您必须指定接下来必须恢复哪个对称协程。
对称协程可以用来实现用户态线程(一个对称协程代表一个用户态线程;调度器从一个协程跳转到下一个对称协程,例如下一个用户态线程是调度)比非对称协程更有效。 这很明显,因为对称协程不需要跳回调用者来恢复下一个用户级线程。 非对称协程需要比对称协程更多的上下文切换才能实现相同的功能。
对称协程 - 对称上下文切换 - 最好用“call with current continuation”(Scheme、Ruby ...)等概念来表示。 boost.context 通过实现 callcc()/continuation 来支持这个概念。 因此 boost.coroutine2 不提供对称协程 API - 但是 boost.coroutine2 的非对称协程是通过 boost.context 的 callcc()/continuation 实现的。
【讨论】: