A set of Qt 6 desktop apps that visually animate real multithreading models. Each one ports
a genuine std::thread / std::mutex / std::condition_variable / std::atomic console
program into a dedicated, GUI-free backbone class and renders what its worker threads report —
the GUI thread is always a pure consumer that only paints, never blocks. Every project shares
one visual vocabulary (shape-and-colour tokens, stations, holding areas, rotating "working" arcs,
and accumulating outcome piles) so the difference between the patterns is what stands out.
| # | Project | Pattern | Sync primitives | Outcomes |
|---|---|---|---|---|
| 01 | Single-Slot CV Hand-off | producer → consumer | mutex + condition_variable |
Displayed / Dropped |
| 02 | Multi-Producer Bounded Queues | N producers → 1 consumer | per-queue mutex, atomic |
Displayed / Dropped / Skipped |
| 03 | Staged Pipeline + Thread Pool | pipeline + worker pool | bounded MPMC channel (2× condition_variable) + future pool |
Consumed / Throttled |
| 04 | Work-Stealing Scheduler | work-stealing pool | mutex-per-deque + atomics |
Ran (own) / Stolen |
Each row links to a project; each project also ships an
ARCHITECTURE.md with its threading-model diagram and data
flow, and a docs/screenshot.png. The build badge above covers all four (one repo-wide CI
run across Ubuntu, Windows and macOS).
- Genuine concurrency, not faked on a timer. The threading lives in a backbone class
(
FramePipeline/QuadPipeline/PipelineEngine/WorkStealingPool) that knows nothing about painting. Worker threads emit Qt signals delivered withQt::QueuedConnection; the GUI marshals them onto its event loop and only animates. - The GUI is never blocked. Custom item types crossing threads are registered with
Q_DECLARE_METATYPE+qRegisterMetaType. Where two different threads can announce events for the same item out of order, the canvas parks the furthest-announced stage and fast-forwards the token once it spawns — so nothing is ever stranded on screen. - Cooperative shutdown. Every app sets a stop flag, wakes all threads, drains in-flight work,
and
join()s — no thread is killed mid-task. - Watchable pacing. The real models run in tens of milliseconds; each visualiser slows the hand-off to hundreds of ms so the behaviour is legible at ~60 fps.
- Same layout, same build. Each project follows an identical structure
(
src/,docs/, top-levelARCHITECTURE.md/CMakeLists.txt/LICENSE/README.md) and builds cross-platform with CMake (Qt 6 or Qt 5,Threads::Threads); CI is repo-wide.
Each app is the visual analogue of a small standalone console program. A copy of the relevant
skeleton lives in that project's src/ (e.g. concurrency-04/src/work_stealing_pool_core.cpp)
— it is reference material that distils the threading model, not compiled into the app.
The projects are OS-independent. From inside a project folder:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="<your-qt-kit-dir>"
cmake --build buildThe result is build/<App> (Linux), build/<App>.app (macOS), or build/<App>.exe (Windows;
the Qt runtime is auto-deployed next to the exe via windeployqt). See each project's README for
platform-specific notes and the run.ps1 / run.sh launchers.
A repo-level .github/workflows/build.yml builds all four
projects across Ubuntu, Windows and macOS on each push/PR, smoke-tests each binary headlessly on
Linux (QT_QPA_PLATFORM=offscreen), and uploads the built artifacts — this is what the build
badge at the top reflects. It is the one workflow in the repo; the projects have no separate
CI of their own.
MIT © 2026 Cosmin Mandachescu — each project also carries its own copy.