<table>
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>Doc. No.:</td>
<td>P0991R0</td>
</tr>
<tr>
<td>Date:</td>
<td>2018-03-12</td>
</tr>
<tr>
<td>Reply to:</td>
<td>Detlef Vollmann, dv@vollmann.ch</td>
</tr>
<tr>
<td>Audience:</td>
<td>SG1</td>
</tr>
</tbody>
</table>
<h1>Comparison of Stackful Coroutine Proposals</h1>
<p>This is a try to understand the differences between the various
(stackful) coroutine proposals.  It may be useful to others as well.</p>
<h3>Terminology</h3>
<p>While the distinction between <em>symmetric</em> and <em>asymmetric</em> seems to be
established in literature, it's confusing to me.
So I use <em>switch_to</em> for what is otherwise called <em>symmetric</em> and
<em>suspend/resume</em> for what others call <em>asymmetric</em>.</p>
<h3>Blocking</h3>
<p>For coroutines switch_to and suspend are blocking calls.
switch_to is inherently boost blocking, suspend not necessarily.</p>
<p>P0073R2 is the only one that proposes an explicit blocking interface.</p>
<h3>Scheduling</h3>
<p>All except P0073R2 assume direct switching without scheduler.</p>
<h2>Characteristics</h2>
<p>For a simplified comparison, some base characteristics were chosen.</p>
<h4>compiler vs. library</h4>
<p>While it's understood that any coroutine proposal will contain
some implementation that's not possible in pure C++ (involving
assembler code or compiler intrinsics), some proposals require
pretty heavy compiler support.</p>
<h4>explicit context</h4>
<p>Some proposals require explicit passing/storing of a context object
(that's returned by switch_to/resume).
In other proposals it's just the state of the (stable) coroutine object.</p>
<h4>global state</h4>
<p>Some proposals require implicit global/thread_local state.</p>
<h4>stack allocation/organization control</h4>
<p>For stackful coroutines it's sometimes important how the (side) stack
is organized and allocated.</p>
<h4>switch_to/suspend to main</h4>
<p>Allows to switch_to any context, even if not created as coroutine
(especially main() or top-level thread functions).</p>
<h4>direct data transfer</h4>
<p>Allows the switch_to/suspend/resume to transfer data directly.</p>
<h4>switch_to</h4>
<p>As the switch_to approach is generally more expressive and suspend/resume
can generally be built on top of switch_to with no nearly no overhead
all but N3708 support switch_to, so it's not a separate coloumn in
the table below.</p>
<h4>suspend/resume</h4>
<p>Some proposals support suspend/resume in addition to switch_to.</p>
<h4>syntax</h4>
<p>Most proposals provide a pure library interface, but some use a
special syntax or keywords.</p>
<h4><code>current()</code></h4>
<p>Some proposals provide a function to get a handle to the current coroutine.</p>
<h2>Proposals included in this comparison</h2>
<ul>
<li>2013-09/N3708: A proposal to add coroutines to the C++ standard library (Oliver, Nat)</li>
<li>2014-05/N3985: A proposal to add coroutines to the C++ standard library (R1) (Oliver, Nat)</li>
<li>2015-04/N4397: A low-level API for stackful coroutines, (Oliver)</li>
<li>2015-04/N4398: A unified syntax for stackless and stackful coroutines, (Oliver)</li>
<li>2015-09/P0099r0: A low-level API for stackful context switching (Nat, Oliver)</li>
<li>2016-06/P0073r2: On unifying the coroutines and resumable functions proposals (Torvald)</li>
<li>2016-10/P0099r1: A low-level API for stackful context switching (Nat, Oliver)</li>
<li>2017-02/p0534r0: call/cc (Oliver)</li>
<li>2017-06/p0534r1: call/cc (Oliver)</li>
<li>2017-07/p0534r2: call/cc (Oliver)</li>
<li>2017-10/p0534r3: call/cc (Oliver)</li>
<li>2018-02/p0876r0: fibers without scheduler (Oliver)</li>
</ul>
<h2>Comparison</h2>
<table>
<thead>
<tr>
<th align="left">Paper</th>
<th align="center">Compiler</th>
<th align="center">Explicit Context</th>
<th align="center">Global State</th>
<th align="center">Stack Alloc Control</th>
<th align="center">suspend / resume</th>
<th align="center">switch_to main</th>
<th align="center">Direct Data Transfer</th>
<th align="center">Syntax</th>
<th align="center"><code>current()</code></th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">N3708</td>
<td align="center">no</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">yes</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">no</td>
</tr>
<tr>
<td align="left">N3985</td>
<td align="center">no</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">yes</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">no</td>
</tr>
<tr>
<td align="left">N4397</td>
<td align="center">no</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">yes</td>
</tr>
<tr>
<td align="left">N4398</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">yes</td>
</tr>
<tr>
<td align="left">P0099R0</td>
<td align="center">no</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">no</td>
<td align="center">yes</td>
</tr>
<tr>
<td align="left">P0073R3</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">?</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">?</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">?</td>
</tr>
<tr>
<td align="left">P0099R1</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">no</td>
</tr>
<tr>
<td align="left">P0534R0-2</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">no</td>
</tr>
<tr>
<td align="left">P0534R3</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">no</td>
<td align="center">no</td>
</tr>
<tr>
<td align="left">P0876R0</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">yes</td>
<td align="center">no</td>
<td align="center">no</td>
<td align="center">no</td>
</tr>
</tbody>
</table>
<h2>Remarks to specific papers</h2>
<h3>N3708/N3985</h3>
<p>No direct suspend/resume/switch_to API, but more generator targeted
<code>pull_type</code> and <code>push_type</code> with direct data transfers.</p>
<h3>N4397/N4398</h3>
<p>Special syntax for resumable lambdas.
N4398 allows the compiler to decide between stackless and stackfull.</p>
<h3>P0099r0</h3>
<p>Conceptually like N4397, but pure library syntax.</p>
<h3>P0073r2</h3>
<p>Mostly (heavy) compiler techniques for unification and common syntax
for stackless and stackful coroutines.</p>
<ul>
<li>not much on concrete API</li>
<li>suspend model assumes scheduler<ul>
<li><code>block()</code> as hint which coroutine to resume</li>
</ul>
</li>
<li>switch_to semantics via blocking interface</li>
<li>
<p><code>class event</code> as context object</p>
</li>
<li>
<p>low-level as it provides mechanisms for higher-level coroutine executors</p>
</li>
<li>high-level as it hides the execution context and assumes scheduler</li>
</ul>
<h3>P0099r1</h3>
<p>Pretty different from P0099R0 to avoid global state.</p>
<h3>P0534r0 to r2</h3>
<p>Based on P0099R1, no major differences</p>
<h3>P0534r3</h3>
<p>Update of P0534R2 without direct data transfer.</p>
<h3>P0876r0</h3>
<p>Essentially a rename of P0534R3.</p>
<h2>Assumptions</h2>
<ol>
<li>switch_to interface is required</li>
<li>no scheduler</li>
</ol>
<h2>Questions</h2>
<ol>
<li>Are unified proposals dead?</li>
<li>Is suspend/resume required?</li>
<li>Is global state acceptable?<ul>
<li>Is for avoiding global state more undefined behaviour acceptable?</li>
<li>Is switch_to main required?</li>
<li>Is a more complicated interface (w/o direct mapping to executors) ok?</li>
</ul>
</li>
<li>Is there a mechanism to help the compiler to inline a context switch?</li>
<li>Should a proposal include a blocking interface?</li>
<li>Is control of stack allocation and organization required?</li>
<li>Does anybody want direct data transfer?</li>
</ol>