Skip to content

v1.0.0

Latest

Choose a tag to compare

@github-actions github-actions released this 28 Jul 07:44
· 121 commits to main since this release

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/ResultState replacing std::packaged_task + std::future.
  • Process-wide ThreadMarket of 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) and detach() (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 Task wrapper 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 Task storage avoids a heap allocation per submitted callable in the common case.
  • ResultState is a single, purpose-sized heap allocation per enqueue(), replacing std::packaged_task's larger general-purpose shared state.
  • Spin → yield → park backoff avoids paying park/wake syscall latency for short-lived bursts of work.
  • ThreadMarket reuses already-running OS threads across ThreadPool lifetimes, 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.