11

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.

Demo 11Source on GitHub ↗

The full source for this example lives in examples/concurrency/11-coroutines-in-depth/ — clone the repo, cd in, 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