非对称协程和对称协程有什么区别?

What is the difference between asymmetric and symmetric coroutines?

我注意到在 C++ 的 Boost.Coroutine2 中删除了对对称协程的支持,所以我想了解 -- 两者之间有什么区别?

Ana Lúcia de Moura 和 Roberto Ierusalimschy 在他们的论文“Revisiting Coroutines”中特别详细地描述了对称和非对称协程之间的区别:

A well-known classification of coroutines concerns the control-transfer operations that are provided and distinguishes the concepts of symmetric and asymmetric coroutines. Symmetric coroutine facilities provide a single control-transfer operation that allows coroutines to explicitly pass control between themselves. Asymmetric coroutine mechanisms (more commonly denoted as semi-symmetric or semi coroutines) provide two control-transfer operations: one for invoking a coroutine and one for suspending it, the latter returning control to the coroutine invoker. While symmetric coroutines operate at the same hierarchical level, an asymmetric coroutine can be regarded as subordinate to its caller, the relationship between them being somewhat similar to that between a called and a calling routine.

Coroutine mechanisms to support concurrent programming usually provide symmetric coroutines to represent independent units of execution, like in Modula-2. On the other hand, coroutine mechanisms intended for implementing constructs that produce sequences of values typically provide asymmetric coroutines. Examples of this type of construct are iterators and generators.

(省略引文)

在非对称协程模型中,"asymmetry"是指协程之间存在stack-like调用者-被调用者关系。协程可以调用另一个协程,也可以通过将控制权交给其调用者来挂起自身,通常还会同时向调用者产生一个值。

在对称协程模型中,一个协程可以不受限制地将控制权让给任何其他协程。

这两个模型实际上具有相同的表达能力;即非对称协程可以使用对称协程实现,反之亦然。 (参见 Symmetric coroutines,由 Giovanni P. Deretta 撰写,了解两种协程之间的转换。)因此,Moura 和 Ierusalimschy 写道:"Providing both constructs only complicates the semantics of the [coroutine] mechanism, with no increase in its expressive power."

Coroutine2 的开发人员决定不在库中提供对称协程,因为他们认为 boost::context::execution_context (part of Boost.Context): http://lists.boost.org/Archives/boost/2015/06/223701.php

可以更好地实现对称协程功能

协程在调用者和被调用者之间切换,例如您输入协程函数,然后切换回调用代码。通常(非对称)协程有两个功能用于此目的:

  • 调用者调用的恢复函数
  • 从协程内部调用的挂起函数

因为你有两个函数来切换上下文,所以叫做不对称。 对称协程只有一个函数可以挂起当前上下文并恢复另一个上下文。请注意,您必须指定接下来必须恢复哪个对称协程。

对称协程可用于实现用户态线程(一个对称协程代表一个用户态线程;调度器从一个协程跳转到下一个对称协程,例如下一个用户态线程被调度)比非对称协程更高效。 这是显而易见的,因为对称协程不需要跳回到调用者来恢复下一个用户线程。 非对称协程需要比对称协程更多的上下文切换才能实现相同的功能。

对称协程 - 对称上下文切换 - 更好地表示为“调用当前延续”(方案,Ruby ...)等概念。 boost.context 通过 callcc()/continuation 的实现来支持这个概念。 因此 boost.coroutine2 不提供对称协程 API - 但 boost.coroutine2 的非对称协程是通过 boost.context 的 callcc()/continuation 实现的。