Repository navigation
ThreadPoolPro v1.0.0
The first stable release of ThreadPoolPro, a high-performance work-stealing C++ thread pool for modern C++.
Highlights
- Lock-free, per-worker Chase-Lev work-stealing deques for local task storage.
- Type-erased task storage with small-buffer optimization — no allocation for small, nothrow-movable callables.
- Sharded, mutex-guarded injection queues for submissions from non-worker threads.
- Lightweight
Future/ResultStatereplacingstd::packaged_task+std::future. - Process-wide
ThreadMarketof leased, persistent OS threads — cheap pool construction/destruction after warm-up. - Atomic wake-token park/wait for worker synchronization instead of
condition_variable+ mutex. enqueue()(with result) anddetach()(fire-and-forget) submission APIs.- Pause/resume support for in-flight task execution.
- Graceful and immediate shutdown modes (
FinishTasks/DiscardTasks). waitIdle()— blocks until the pool drains, helping steal/execute tasks itself rather than sitting idle.- Runtime statistics: active tasks, queued tasks, exception count, idle thread count.
- Move-only, exception-safe
Taskwrapper with explicit heap/inline storage paths.
Performance
The implementation is designed to minimize contention and avoid unnecessary allocation on the hot submit/execute path.
- Local push/pop costs no atomic read-modify-write in the uncontended case.
- Randomized steal-victim offsets spread contention across workers instead of serializing on the same low-index victim.
- Sharded injection queues avoid a single shared lock becoming the dominant contention point as worker count grows.
- Small-buffer-optimized
Taskstorage avoids a heap allocation per submitted callable in the common case. ResultStateis a single, purpose-sized heap allocation perenqueue(), replacingstd::packaged_task's larger general-purpose shared state.- Spin → yield → park backoff avoids paying park/wake syscall latency for short-lived bursts of work.
ThreadMarketreuses already-running OS threads acrossThreadPoollifetimes, avoiding thread-creation cost on repeated construction/destruction.
Benchmarks
Measured against oneTBB at 10K / 100K / 1M iterations (and 1k–100k for
worker-count scaling). Full results: benchmarks/results/v1_0_0.md.
| Operation | ThreadPoolPro (1M) | oneTBB (1M) | Δ |
|---|---|---|---|
| Detach (caught exception) | 114.18 ms | 133.30 ms | +16.7% |
| Detach Single Task | 376.76 ms | 157.34 ms | -58.2% |
| Enqueue + Result | 941.76 ms | 168.78 ms | -82.1% |
| Detach Batch + Drain (64 tasks) | 50.60 s | 3.44 s | -93.2% |
| Construct + Destroy | 10.63 s | 621.59 ms | -94.2% |
| Worker Count 32 (100k tasks) | 26.38 s | 1.30 s | -95.1% |
| Worker Count 8 (100k tasks) | 92.94 s | 1.29 s | -98.6% |
ThreadPoolPro currently trails oneTBB — a mature, heavily-tuned
production library — on nearly every apples-to-apples throughput
comparison, sometimes substantially so at higher worker counts and
batch sizes. The one exception measured is the caught-exception path
under detach(), where ThreadPoolPro is modestly faster.
Everything else measured (single-callable invoke, state queries, raw
queue push/pop/steal, move construction, pause/resume cycling) has no
oneTBB equivalent benchmarked here, so those numbers are reported
without a comparison baseline; see the full results file for the raw
figures.
This is a first release: the design choices documented throughout the
codebase (sharded injection queues, randomized steal offsets, the
SBO'd Task, the leased-thread ThreadMarket) address specific
contention points found during development, but oneTBB's task-stealing
scheduler has years of production tuning behind it that this library
doesn't yet match. Closing this gap is expected follow-up work rather
than a claim this release makes.
Testing
The project includes a comprehensive test suite covering:
- Unit tests
- Integration tests
- Lifecycle tests
- Move semantics
- Regression tests
- Exception safety
- Task submission and retrieval (local queue, stealing, injection shards)
- Pause/resume behavior
- Shutdown modes (
FinishTasks/DiscardTasks), including self-detach from within a running task - Future/ResultState lifecycle, including error paths
- VTable operation round-trips (invoke, move, destroy, heap-delete)
Code Coverage
The current test suite achieves:
- 93.3% line coverage (513 / 550 lines)
- 96.9% function coverage (377 / 389 functions)
Per-directory breakdown:
| Directory | Line Coverage | Function Coverage |
|---|---|---|
include/ThreadPoolPro |
87.9% (29/33) | 97.7% (42/43) |
include/ThreadPoolPro/Detail |
91.9% (102/111) | 96.6% (284/294) |
src/ThreadPoolPro |
94.3% (200/212) | 96.0% (24/25) |
src/ThreadPoolPro/Detail |
93.8% (182/194) | 100.0% (27/27) |
Coverage reports exclude test infrastructure and third-party dependencies, focusing on the ThreadPoolPro library implementation.
Continuous Integration
Automated builds and tests are configured for:
- GCC — Debug
- GCC — Release
- Clang — Debug
- Clang — Release
- MSVC — Debug
- MSVC — Release
- AppleClang — Debug
- AppleClang — Release
Release
This release represents the first stable version of ThreadPoolPro and establishes the initial API, synchronization design, testing infrastructure, and cross-platform CI pipeline.
Installation
Clone the repository and integrate ThreadPoolPro into your C++ project using the provided CMake configuration, or install via the Conan recipe or vcpkg port under packaging/.
See the project documentation for build instructions, API usage, and integration details.