Papers
Topics
Authors
Recent
Search
2000 character limit reached

Asymmetric Coroutines

Updated 11 July 2026
  • Asymmetric coroutines are a programming construct that restricts control transfer to a designated caller or scheduler, ensuring structured resumption.
  • They are implemented via strategies such as closure-based state machines, partial CPS conversion, and standardized coroutine frames to manage resources efficiently.
  • Formal models and behavioral type systems for asymmetric coroutines guarantee yield safety and correctness, shaping advances in embedded and concurrent systems.

Searching arXiv for papers on asymmetric coroutines and related formal models. arxiv_search(query="asymmetric coroutines stackless stackful coroutine types expressive power", max_results=10, sort_by="relevance") Searching for formal and systems papers that explicitly discuss asymmetric coroutines. arxiv_search(query="\"asymmetric coroutines\" arXiv", max_results=10, sort_by="relevance") Asymmetric coroutines are coroutines in which control transfer is restricted to a distinguished caller, parent, scheduler, or runtime, rather than being passed explicitly from one coroutine to any other. Coroutines broadly “extend the concept of a function by adding suspend and resume operations,” and the asymmetric/symmetric distinction is one of the main axes along which the literature classifies them (Belson et al., 2019). A 2018 implementation paper states that it focuses on “stackless asymmetric coroutines,” while a 2025 expressiveness study places asymmetric coroutines alongside one-shot effect handlers and one-shot delimited-control operators in Felleisen’s macro-expressiveness framework (Racordon, 2018, Kobayashi et al., 15 Sep 2025). Across the literature, asymmetric coroutines appear as stackless state machines, stackful runtime contexts, first-class coroutine values, typed behavioral protocols, and scheduler-mediated task abstractions.

1. Defining asymmetry and its main variants

A concise contrast appears in the literature that distinguishes symmetric coroutines, where control can be passed explicitly “from one coroutine to any other,” from semi-symmetric/asymmetric coroutines, where transfer is restricted to “parent/child relationships in the call stack” (Racordon, 2018). A closely related survey of embedded systems does not explicitly organize its taxonomy around the symmetric/asymmetric distinction, but it repeatedly describes mechanisms in which a coroutine suspends to an enclosing runtime or scheduler and is later resumed by that external agent; this suggests that many embedded coroutine mechanisms are asymmetric in practice (Belson et al., 2019).

Asymmetry is orthogonal to several other design choices. One is stackfulness. The embedded-systems survey defines a stackful coroutine as one that “has its own stack which is not shared with the caller,” whereas a stackless coroutine “pops its state off the stack during suspension (like a normal function return)” (Belson et al., 2019). Another is first-class status. QEMU’s coroutine API is described as implementing “first-class, stackful, asymmetric coroutines, with no value passing upon suspension and resumption,” while later typing work studies “asymmetric, first-class, stackless coroutines” (Kerneis et al., 2013, GU et al., 2023). A common misconception is therefore that asymmetry implies stacklessness or a particular runtime layout; the published examples show both stackful and stackless asymmetric designs.

The same point applies to the programming interface. Some systems use explicit yield/resume pairs, some use co_await, co_yield, and co_return, and some expose coroutine behavior indirectly through handlers, schedulers, or typed interaction traces. What remains stable is the asymmetry of control: suspension returns to a distinguished resumption context, and later progress is determined by a caller, scheduler, or runtime rather than by arbitrary peer-to-peer transfer (Belson et al., 2019, Kerneis et al., 2013).

2. Operational semantics and formal models

One of the clearest formal accounts is the calculus λ\lambda_{\leadsto}, presented as a typed model of “delimited, stackful coroutines with snapshots” (Prokopec et al., 2018). Its surface constructs include coroutine definitions, instance creation with start, suspension with yield, resumption with resume, and duplication with snapshot. The type distinction is central: a coroutine definition has type

T1TyT2,T_1 \overset{T_y}{\rightsquigarrow} T_2,

while a coroutine instance has type

TyT2.T_y \leftrightsquigarrow T_2.

This separates a coroutine body from a first-class instance that can be resumed.

The operational discipline in that calculus is explicitly asymmetric. A coroutine is resumed by an external context through resume(t,v_2,v_3,v_4). If the coroutine yields, the yielded value is passed to the yield handler, and the suspended remainder is stored back into the coroutine instance; if it terminates, the completion handler runs; if it is already done or already executing, the fourth branch is taken (Prokopec et al., 2018). The paper’s “Yield safety” corollary states that a well-typed user program never evaluates to a suspension term, which formalizes delimitation: yields return only to a matching resumption context.

A different but related line of work studies functional coroutines through a verified abstract machine. There, a functional coroutine is represented not just by a continuation, but by a pair

environment,continuation,\langle \text{environment}, \text{continuation} \rangle,

and the restriction is enforced through safe λμ\lambda\mu-terms (Crolard, 2016). The paper characterizes these as “a restricted, logically disciplined form of asymmetric coroutines,” because context switching remains, but no coroutine may access another coroutine’s local environment. This gives a machine-checked account of stackful asymmetric control in which saved state is environment-sensitive rather than merely continuation-based.

These formal models also show that asymmetry does not fix resumability to a single pattern. The closure-based encoding discussed below is effectively one-shot, because the saved state is overwritten destructively at each resumption, while λ\lambda_{\leadsto} supports repeated resumption over time and extends ordinary asymmetric behavior with snapshot, which duplicates suspended state (Racordon, 2018, Prokopec et al., 2018).

3. Typing, composition, and behavioral analysis

A separate strand of research studies asymmetric coroutines at the level of types. “Typing Composable Coroutines” introduces a type notation and calculus for “asymmetric, first-class, stackless coroutines” in which a coroutine type has two components: a receiving part and a yielding part (GU et al., 2023). The paper’s stated goal is to compute, from a list of coroutine types and their activation order, a single composed type describing the group’s “collective behavior.” Internal yield/resume interactions are discharged compositionally, and what remains is the externally visible receive/yield protocol.

This calculus is intentionally order-sensitive. The paper states that the order of coroutines in the sequence must match the order when they are first activated, and composition uses a first selection rule to determine which coroutine yields or receives next (GU et al., 2023). A plausible implication is that the type system is modeling a deterministic single-threaded scheduling discipline rather than an abstract commutative composition law. The same work also treats coroutines as first-class communicated values, so coroutine types may themselves be yielded or received.

Behavioral typing is extended further by the Flow extension to Coroutine Types for Go deadlock detection. That work starts from Coroutine Types that modeled only “a single receiving operation followed by a single yielding operation,” and extends them so that yielding and receiving “can happen in any order for an unlimited number of times” (Gu et al., 23 Feb 2026). The syntax includes yielded items, received items, coroutine definition types, coroutine instance types, constrained types, and unions. Its reduction semantics tracks a Pending Type and External Yields; if the reduction result is 0, “the two channel operations are paired properly and the program has no deadlocks” (Gu et al., 23 Feb 2026).

The Go mapping is explicit: the keyword go is mapped onto \Start, function definitions onto coroutine definitions, and channel send/receive operations onto yielding and receiving primitives (Gu et al., 23 Feb 2026). This is not a runtime implementation of asymmetric coroutines in the conventional language-design sense, but it is a behavioral model of asymmetric yield/receive protocols. The paper reports recognition of “17 patterns of channels and goroutine interactions,” including nested goroutines and mismatched senders and receivers.

4. Implementation strategies

One of the simplest implementation models compiles a coroutine into a closure over mutable local state plus an explicit instruction pointer inst. In the 2018 higher-order-function paper, a coroutine instance is a returned closure that captures locals and inst; each call resumes execution from the current state, and each yield becomes “save next state and return” (Racordon, 2018). The paper describes this as focusing on “stackless asymmetric coroutines,” and its transformation proceeds by constructing a control-flow graph, turning blocks into switch cases, and wrapping dispatch in a loop so that non-yielding blocks continue immediately. Because the closure state is mutated destructively, resumptions are effectively one-shot.

A more industrial compilation route is partial CPS conversion. QEMU/CPC studies QEMU’s source-level model of “first-class, stackful, asymmetric coroutines” and shows how to re-implement that model using selective CPS conversion and static annotation checking (Kerneis et al., 2013). Cooperative functions are annotated and transformed; native functions remain in direct style. CoroCheck builds a directed call graph, propagates coroutine-ness backwards from callees to callers, and checks annotation consistency, indirect calls, and forbidden calls to blocking_fn functions. The evaluation covers “750 000 lines of C code” and reports that the original QEMU master branch lacked over 70% of the annotations required to compile with CPC (Kerneis et al., 2013).

A third strategy uses standardized coroutine frames. Libfork maps strict fork-join tasks onto C++20 stackless coroutines: each task is a coroutine, each suspended task is represented by its frame or handle, and fork/join are implemented as custom awaitables (Williams et al., 2024). The paper emphasizes that the exposed model remains scheduler-centric and asymmetric, even though C++20 symmetric transfer is used internally as a low-level optimization for zero-stack-growth handoff. This distinction is significant: internal symmetric transfer does not by itself make the programming model a symmetric coroutine system.

Strategy Representative source Salient property
Closure/state machine (Racordon, 2018) Captured locals plus inst
Partial CPS conversion (Kerneis et al., 2013) Cooperative functions become CPS-converted calling convention
Standard coroutine frames (Williams et al., 2024) Suspended handles moved by awaiters and workers

5. Systems practice and application domains

The most systematic empirical overview in the supplied literature is the survey of coroutines in IoT and embedded systems. It analyzes 35 studies published between 2007 and 2018 and reports that “The C & C++ programming languages were used by 22 studies out of 35.” In hardware terms, “16 studies used 8- or 16-bit processors while 13 used 32-bit processors” (Belson et al., 2019). The four most common use cases were “concurrency (17 papers), network communication (15), sensor readings (9) and data flow (7),” and the leading intended benefits were “code style and simplicity (12 papers), scheduling (9) and efficiency (8)” (Belson et al., 2019).

The same survey reports that “27 papers (77%) used a native method,” and among native implementations “13 papers employed macros,” “of which 7 were based on Duff’s device,” “4 used libraries,” and “in 3 papers ... setjmp/longjmp ... was used” (Belson et al., 2019). For API properties, “The overwhelming majority (89%) of implementations managed control flow on behalf of the programmer,” “more than two-thirds managed the state of local variables,” and the surveyed implementations included “11 stackless versus 8 stackful” (Belson et al., 2019). The paper concludes that there is widespread demand for coroutines on resource-constrained devices.

This survey does not explicitly classify systems as asymmetric or symmetric, but it repeatedly emphasizes scheduler-based cooperative execution, async/await-like direct style, generator-like patterns, and protothread-style callback replacement (Belson et al., 2019). This suggests that asymmetric suspend/resume designs dominate in resource-constrained practice. The same survey also ties proposed C++20 support to co_await, co_yield, and co_return, and cites proposal N4680 as “a stackless model that requires all yield or return statements to be contained within the body of the coroutine” (Belson et al., 2019).

Outside embedded systems, QEMU provides a large systems-language example of source-level asymmetric coroutines in a block-I/O setting, while libfork shows that stackless coroutines can support scheduler-centric strict fork-join programming in HPC-style shared-memory environments (Kerneis et al., 2013, Williams et al., 2024).

6. Scheduling, performance, and resource trade-offs

The scheduler is often the concrete bearer of asymmetry. In libfork, co_await suspends the current coroutine and hands its frame to an awaiter; workers later resume frames from local work-stealing queues (Williams et al., 2024). The paper quotes the standard work/span bound

$T_p \le \frac{T_1}{P} + \bigO{T_\infty}$

and the ideal space bound

MpPM1,M_p \le P M_1,

then proves a concrete stack-space theorem for its segmented-stack design:

Mp(2c+3)PM1.M_p \le (2c + 3) P M_1.

Empirically, it reports that compared to openMP (libomp), libfork is “on average 7.2x faster and consumes 10x less memory,” and compared to Intel’s TBB it is “on average 2.7x faster and consumes 6.2x less memory” (Williams et al., 2024).

A different scheduling perspective appears in “Combine-and-Exchange Scheduling” for “tasks that are scheduled entirely in the userspace (e.g., coroutines, fibers, etc.)” (König et al., 12 Nov 2025). The paper argues that user-space runtimes often make the wrong decision at synchronization boundaries. Dispatching the next waiter to an executor preserves parallelism but inserts queueing delay into the critical path; resuming the next waiter inline removes queueing delay but collapses parallelism onto one thread. CES combines critical sections on one thread and exchanges the unlocking task’s post-critical continuation out to the executor. The abstract reports “3-fold performance improvements in application benchmarks as well as 8-fold performance improvements in microbenchmarks,” and the detailed evaluation reports about 8.1× improvement in a mutex microbenchmark at 256 threads and about 3.3× over TCLocks in LevelDB at 256 concurrent operations (König et al., 12 Nov 2025).

These results reinforce a recurring point in the asymmetric-coroutine literature: the cost model is rarely just “suspend versus resume.” It also includes continuation representation, queueing delay, stack allocation policy, locality, and the precise division of labor between runtime and coroutine body. A common misconception is that user-space suspend/resume is automatically lightweight; several papers instead show that the benefits depend on the surrounding scheduler and continuation representation (Williams et al., 2024, König et al., 12 Nov 2025).

7. Expressiveness, restrictions, and adjacent abstractions

Asymmetric coroutines are not only an implementation technique; they have also become an object of expressiveness theory. The 2025 paper “Expressive Power of One-Shot Control Operators and Coroutines” states that it adopts Felleisen’s macro-expressiveness to compare one-shot control operators and that it “verify[ies] the folklore that one-shot effect handlers and one-shot delimited-control operators can be macro-expressed by asymmetric coroutines, but not vice versa” (Kobayashi et al., 15 Sep 2025). In the supplied material, the formal ingredient spelled out in detail is Felleisen’s notion of conservative extension, under which a language extends another by a finite set of additional constructors while preserving the behavior of old programs. A plausible implication is that asymmetric coroutines are being treated there not merely as a library idiom, but as a distinct source of macro-expressive power.

The literature also sharpens several limits. Functional coroutines in the verified abstract-machine work are not unrestricted first-class continuations; they are a “restricted, proof-theoretically disciplined form of asymmetric coroutines” in which no coroutine may access another coroutine’s local environment (Crolard, 2016). The higher-order-function encoding is explicitly stackless and effectively one-shot (Racordon, 2018). By contrast, the λ\lambda_{\leadsto} calculus is stackful and adds snapshot, which can duplicate suspended state (Prokopec et al., 2018). Asymmetry therefore does not determine whether a system is one-shot, multi-resume, snapshot-capable, stackful, or stackless.

Finally, some newer systems are only coroutine-like by analogy. AsyncFC, a framework for LLM tool use, “does not use the term coroutine,” but is described as “very closely analogous to asymmetric coroutines”: the model continues decoding over symbolic futures, the runtime acts as scheduler and executor, and await_future behaves like an explicit await point (Feng et al., 14 May 2026). This suggests that the asymmetric pattern—distinguished caller, external scheduler, delayed resumption—has become a reusable design schema even outside conventional programming-language runtimes.

Topic to Video (Beta)

No one has generated a video about this topic yet.

Whiteboard

No one has generated a whiteboard explanation for this topic yet.

Follow Topic

Get notified by email when new papers are published related to Asymmetric Coroutines.