Repository navigation
docs(r23): Boost.Fiber — example 54 + chapter 54 (Compendium: C++ Concurrency) - #23
Merged
Merged
Conversation
…currency) Sixth chapter of Part 14, and the stackful counterpart to ch53. ch53 measured a stackless coroutine frame at 32 bytes and noted in passing that co_await only works inside a coroutine body. ch54 is about what a real stack costs and what that restriction is worth escaping. The memory trilogy, three instruments across three chapters: thread 8388608 B pthread_getattr_np (ch50) fiber 131072 B stack_traits::default_size() (ch54) coroutine frame 32 B operator new in promise (ch53) 8 MiB -> 128 KiB -> 32 bytes. Both ratios (64, 4096) computed in the program from those measured numbers, never quoted. What the stack buys, demonstrated rather than described: a fiber suspends from inside an ORDINARY non-coroutine function six frames deep and resumes at the same depth. A stackless coroutine cannot express this at any price — co_await colours every frame in the suspend path. The guard page, both directions: protected_fixedsize_stack costs exactly one page more than fixedsize_stack (delta gated against page_size(), not a hardcoded 4096), and recursing 60x past a 64 KiB stack dies with exit 139 (SIGSEGV) rather than corrupting the next mapping. The gate asserts the exit SIGNAL only — output after a stack overflow is undefined — and explicitly rejects 124, since a hung run must not pass a test for faulting promptly. The scheduler is a choice: the same 16 fibers report distinct_tids=1 under the default round_robin and 4 under shared_work, one call to use_scheduling_algorithm apart. That is ch49's grid selected by a line, where ch44's Go runtime decides for you. The TU is compiled -O0 deliberately and the reason is in CMakeLists.txt: at -O2 the recursion can become a loop and never touch the guard page, which would make guard-overflow exit 0 and quietly stop proving anything. ch49's optimizer lesson, one layer down. Two diagrams (Fig 54.1 three ways to pause, Fig 54.2 the scheduler is a choice). System Boost 1.90.0 — no Conan, no network. Verified on the Fedora 44 host: verify.lua PASS 32 / FAIL 0 with the migration, fault, and clang gates all running for real; runner 1 passed; validate.py OK.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Sixth chapter of Part 14, and the stackful counterpart to ch53.
ch53 measured a stackless coroutine frame at 32 bytes and noted in passing that
co_awaitonly works inside a coroutine body. ch54 is about what a real stack costs — and what that restriction is worth escaping.The memory trilogy completes
Three instruments, three chapters, one ordering:
pthread_getattr_npstack_traits::default_size()operator newinpromise_type8 MiB → 128 KiB → 32 bytes. Both ratios (64 fibers per thread stack, 4096 frames per fiber stack) are computed in the program from those measured numbers rather than written into the prose. Nothing here is quoted.
The ordering falls out of one structural fact: a fiber costs more than a frame because it has a stack, and less than a thread because the kernel never sees it — no
task_struct, no tid, nothing in/proc/<pid>/task/.What the stack buys, demonstrated rather than described
A fiber suspends from inside an ordinary non-coroutine function six frames deep and resumes at the same depth. A stackless coroutine cannot express this at any price —
co_awaitcolours every frame in the suspend path, and the colour propagates through third-party functions you cannot edit.128 KiB buys the right to suspend anywhere; 32 bytes restricts you to functions marked in advance.
The guard page, both directions
fixedsize_stack(64 KiB)returns exactly 65536.protected_fixedsize_stack(64 KiB)returns 69632 — exactly one page more, mappedPROT_NONE. The delta is gated againstpage_size()rather than a hardcoded 4096.Recursing 60× past that stack: exit 139 (SIGSEGV) on the guard page, instead of corrupting the next mapping.
Two gate-design details worth flagging:
timeout(1)returns when it kills something, and a hung run must not pass a test that means "faulted promptly".The scheduler is a choice
Same 16 fibers, same work, one line apart:
That is ch49's grid selected by one
use_scheduling_algorithmcall — where ch44's Go runtime decides for you and mostly won't be argued with. Neither answer is right:round_robinmeans a fiber's data is only ever touched by one thread, which removes an entire category of synchronization. Sign gated (> 1, never== 4) with a bounded retry; measured 4 of 4 across five runs.-O0, deliberately, and documentedAt
-O2the recursion can become a loop and never touch the guard page —guard-overflowwould exit 0 and quietly stop proving anything. That's ch49's optimizer lesson one layer down, and the reason is inCMakeLists.txtrather than left implicit.Verification
Fedora 44, system Boost 1.90.0 — no Conan, no network — g++ 16.1.1, clang 22.1.8, local and unprivileged:
LSP_LANG=cpp lua verify.lua→ PASS 32 / FAIL 0, with the migration, fault, and clang gates all running for realpython3 scripts/test-all-examples.py --only 54-boost-fiber→ 1 passedpython3 scripts/validate.py→ OKChapter Ncross-references resolveOne correction before shipping:
fiber_specific_ptris in<boost/fiber/fss.hpp>, not the path I first wrote. Verified by grep. All three named-but-unexercised APIs were confirmed present on this host, and the footer says they are named rather than gated.Two diagrams (Fig 54.1 three ways to pause, Fig 54.2 the scheduler is a choice).