Chapter 11 — Generators, Tasks, and HALO
Hand-rolled generator and task coroutine types, plus an allocation-counting probe, show what a C++20 coroutine frame actually costs and when the compiler can elide it.
The full source for this example lives in
examples/concurrency/11-coroutines-in-depth/— clone the repo,cdin, and./demo.sh.
Chapter reference: Doc 11 — Coroutines in Depth
What it shows
Since C++20 ships coroutines as a language feature with no standard-library coroutine type, this example hand-rolls a co_yield-based generator (consumed and then destroyed mid-suspension, well-defined behavior) and a co_await-able task type whose final suspension performs symmetric transfer instead of a nested .resume() call. A third piece overloads a coroutine promise’s allocation operators to count frame allocations for a coroutine with no live state across a suspension point versus one carrying a 4 KiB buffer across a real co_await — demonstrating the heap-allocation-elision optimization (HALO) the standard permits but never requires. Generator output and the task’s chained result are checked as hard assertions; the allocation counts are reported, not asserted, since HALO elision is toolchain-dependent.
Running it
cd examples/concurrency/11-coroutines-in-depth
./demo.sh # build + run coroutines_in_depth + verify.lua
./demo.sh --clean # remove the image