Characteristic of Coroutines

Get familiar with the characteristics of coroutines.

Coroutines have a few unique characteristics.

Typical use-cases

Coroutines are the usual way to write event-driven applications, which can be simulations, games, servers, user interfaces, or even algorithms. Coroutines are also typically used for cooperative multitasking. The key to cooperative multitasking is that each task takes as much time as it needs, but avoids sleeping or waiting and instead allows some other task to run. Cooperative multitasking stands in contrast to preemptive multitasking, for which we have a scheduler that decides how long each task gets the CPU.

There are different kinds of coroutines.

Underlying concepts

Coroutines in C++20 are asymmetric, first-class, and stackless.

The workflow of an asymmetric coroutine goes back to the caller. This does not hold for a symmetric coroutine. A symmetric coroutine can delegate its workflow to another coroutine.

First-class coroutines are similar to first-class functions since coroutines behave like data. Behaving like data means that you can use them as arguments to or return values from functions, or store them in a variable.

A stackless coroutine is able to suspend and resume the top-level coroutine. The execution of the coroutine and the yielding from the coroutine comes back to the caller. Stackless coroutines are often called resumable functions. They use the stack of the caller.

Design goals

Gor Nishanov describes in proposal N4402 the design goals of coroutines. Coroutines should

  • be highly scalable (to billions of concurrent coroutines)
  • have a highly efficient resume and suspend operations comparable in cost to the overhead of a function
  • seamlessly interact with existing facilities with no overhead
  • have open-ended coroutine machinery allowing library designers to develop coroutine libraries exposing various high-level semantics such as generators, goroutines, tasks, and more
  • usable in environments where exceptions are forbidden or not available

Due to the design goals of scalability and seamless interaction with existing facilities, the coroutines are stackless. In contrast, a stackful coroutine reserves a default stack of 1MB on Windows, and 2MB on Linux.

Becoming a coroutine

There are four ways for a function to become a coroutine.

A function becomes a coroutine if it uses

  • co_return, or
  • co_await, or
  • co_yield, or a
  • co_await expression in a range-based for loop.

Get hands-on with 1200+ tech skills courses.