Prerequisite stack
Figure 0.1 — the prerequisite stack: a Fedora host, the C++ toolchain and Conan, a container engine, an optional KVM lab for the parallelism chapters, and the editor of your choice
Architecture and flow diagrams for the book. Click any
diagram to open it fullscreen. Each is also available as
.excalidraw source — open it on
excalidraw.com
to edit.
Figure 0.1 — the prerequisite stack: a Fedora host, the C++ toolchain and Conan, a container engine, an optional KVM lab for the parallelism chapters, and the editor of your choice
Figure 1.1 — the four execution models formed by crossing structure (concurrency) and execution (parallelism)
Figure 2.1 — the cache hierarchy's rough latencies, and the MESI states a cache line moves through to stay coherent across cores
Figure 2.2 — a context switch's direct cost is small; its indirect cost is the cache working set it evicts, paid back in the misses that follow
Figure 3.1 — a wall-clock deadline can recede when NTP steps the clock; a steady_clock deadline cannot
Figure 3.2 — one deadline value carried unchanged through every hop, versus each hop re-deriving its own timeout and silently multiplying the caller's budget
Figure 4.1 — jthread's owned stop_source, the stop_token handed to the worker, and the destructor's automatic request_stop-then-join
Figure 5.1 — one lock word, two paths: the uncontended compare-exchange never leaves user space; only a lost compare-exchange descends into the kernel
Figure 6.1 — the same opposing acquisition order, fatal with lock_guard and safe with scoped_lock
Figure 7.1 — latch (single-use countdown), barrier (reusable phased rendezvous with a completion function), and counting_semaphore (ownerless permit pool) side by side
Figure 8.1 — the same producer/consumer hand-off under three orderings: seq_cst's global total order, acquire/release's single happens-before edge, and relaxed's bare atomicity
Figure 9.1 — the ABA problem on a lock-free stack: T1 reads head=A and computes new_head=A->next, is preempted, T2 pops A and B and pushes a new node that reuses address A, and T1's CAS succeeds against a head value that is numerically A but semantically a different stack
Figure 10.1 — a future's get() blocks the consumer thread on one producer; a coroutine's co_await attaches a continuation without blocking it, over the same exception-propagation guarantee
Figure 11.1 — HALO is a permission, not a guarantee: identical source at an identical optimization level can allocate on one toolchain and elide entirely on another, both conforming
Figure 12.1 — Chapter 11's ReadAwaitable, wired to a real epoll reactor: await_suspend parks the handle, epoll_wait resumes the exact handle that fd belongs to
Figure 13.1 — three ways to hold a paused computation: a thread's kernel-visible stack, a fiber's user-space stack, and a coroutine's heap frame, in decreasing cost and increasing restriction on where they may suspend
Figure 14.1 — what each execution policy permits the library to do with your callable, and what it forbids the callable from doing in return
Figure 15.1 — a work-stealing pool: each worker pops its own freshly pushed work from the bottom of its deque, and an idle worker steals the oldest task from the top of a busy neighbor's deque
Figure 16.1 — first-touch allocation binds a buffer to the initializing thread's node; workers on other nodes pay the remote-latency penalty on every access for the buffer's lifetime
Figure 17.1 — a scalar add processes one lane; a vector add processes as many lanes as fit in the register, for roughly the same per-instruction cost
Figure 17.2 — AoS scatters one field's values across gaps of unrelated fields; SoA packs each field contiguously, which is what a vector load actually needs
Figure 18.1 — a closed-loop timer records one sample for a stall; a fixed-rate caller actually experiences several queued requests behind it
Figure 19.1 — one round trip two ways: an unpinned, heap-allocating, blocking path against a pinned, buffer-reusing, busy-polling one
Figure 20.1 — two atomics on one cache line force coherence traffic on every write; padding each onto its own line removes it
Figure 21.1 — the ring as a messaging channel: a single producer claims and publishes slots, independent consumers trail the published sequence at their own pace, and the slowest consumer's position gates how far the producer can run ahead
Figure 22.1 — the two IPC families and the mechanism ladder from tightest coupling (shared memory) to loosest (D-Bus)
Figure 23.1 — actor mailboxes are addressed point-to-point by actor identity; CSP channels are anonymous conduits any sender or receiver can use, with select multiplexing several at once
Figure 24.1 — accepted requests split at the capacity gate: handled below the in-flight cap, shed with 503 above it, with the shed path doing no handler-side work
Figure 25.1 — tag-based dispatch: each CallData state machine issues operations tagged with itself, a pool of threads pulls completed tags off the queue, and each tag drives its own call forward
Figure 26.1 — the same thrown exception at three boundaries: terminated outright from a detached thread, stored and rethrown from a future, stored and rethrown from a coroutine's own Task wrapper
Figure 27.1 — thread apply all bt on the hung AB/BA deadlock, reading the lock cycle directly off two threads' backtraces and the mutexes' own owner fields
Figure 27.2 — a representative TSan report's five sections mapped to what the instrumentation actually tracked: two conflicting accesses, the raced-on location, and each thread's creation site
Figure 28.1 — the same race, two independent detection algorithms: TSan's per-thread vector clocks versus Helgrind's lockset-and-happens-before hybrid, converging on the identical source line
Figure 29.1 — a trace's context does not cross a thread boundary on its own: a thread-pool task and a coroutine resumption both have to capture the parent Context explicitly and reinstall a Scope before any child span is created on the new thread
Figure 30.1 — a comment-guarded member leaves unlocked access compiling fine; a Monitor
Figure 31.1 — a SEDA pipeline: independently pooled and queued stages, with a fan-out/fan-in detour around the Compute stage joined by a latch before the pipeline continues
Figure 32.1 — cpu.max throttles aggregate time across all visible cores; cpuset.cpus restricts which cores are visible at all, with no time accounting
Figure 33.1 — the full ingest-to-publish pipeline: many ingest threads feeding a single pinned match thread over a lock-free ring, fanning out through a second ring to several publish threads, with an OTel span carried through every stage
Figure 34.1 — one source tree, a pinned Conan lockfile, five CMake presets including a GCC parity leg, and one Lua harness gating every binary against the same observable-effect checks