thread-pool is a compact, cross-platform thread pool library written for C++23 using modules and dependency injection. The design emphasizes flexibility, zero-cost abstractions where possible, and safe, explicit semantics. You can customize the pool with:
- Custom
Tasktypes (any callable satisfying the library'staskconcept) - Custom
TaskQueueimplementations (custom queue/storage strategies) - Custom
Policyhooks (optional lifecycle hooks called at various points) - Custom
ThreadAllocatortype
- Minimal runtime overhead: most cost comes from
TaskandTaskQueueimplementations. - Highly customizable through concepts and templates.
- Optional hooks (no need to implement all policy methods).
- Dynamic thread management: increase/decrease thread count at runtime.
- Designed for
noexceptusage where possible to make behavior predictable.
The implementation favors noexcept operations and clearly defines where hooks and allocations may occur. It uses modern C++ features (modules, concepts, std::jthread, std::stop_token/stop_source, and std::expected) and ships with sensible defaults:
DefaultTask— A type-erased callable wrapper intended fornoexceptcallables (construction may allocate).DefaultQueue<T>— Mutex-protected queue usingstd::pmr::unsynchronized_pool_resource.DefaultPolicy— Default policy with sensible behavior (invokes failed-to-enqueue tasks when applicable).
- You need a flexible thread pool that can be adapted to different task and queue types.
- You want to leverage C++23 features for better concurrency and resource management.
- You want to avoid the complexity of building a thread pool from scratch while retaining control over its behavior.
- You want to experiment with different scheduling and queuing strategies via dependency injection.
- You want a thread pool that can be easily integrated into modern C++ projects using modules and CMake.
- You need a ready-to-use and very high-performance thread pool with lock-free queues and minimal overhead; consider specialized libraries.
- You are using an older C++ standard (pre-C++23) that does not support the required features.
- C++23-compatible compiler (GCC 15+, Clang 17+, MSVC 19.36+(Visual Studio 2022 17.6+)).
- CMake 3.30+ (for building).
- A CMake generator that supports C++20 modules, such as Ninja (Visual Studio and Unix Makefiles may have issues with module dependencies in some versions).
Important: Because this library uses
import std, you must enable CMake’s experimentalimport stdsupport beforeCXXis enabled (usually aproject()call), otherwise you will get an error like:Experimental import std support not enabled when detecting toolchain; it must be set before CXX is enabled (usually a project() call).You can enable it in one of two ways:
Include the helper script (shipped in the repository) once in your top-level
CMakeLists.txtbefore the firstproject()call:include(path/to/thread-pool/cmake/SetupImportStd.cmake)This automatically sets the correct UUID for your CMake version.
Set the variable manually before the first
project()call. Check the CMake docs for the UUID that matches your exact CMake version, then use:set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "<UUID for your CMake version>")
git submodule add https://github.com/Millforge/thread-pool.git external/thread-poolIn your CMakeLists.txt:
add_subdirectory(external/thread-pool)
target_link_libraries(your-target PRIVATE thread-pool::thread-pool)- Install the library to your system or packaging prefix (provide a CMake install step in the project).
git clone https://github.com/Millforge/thread-pool.git
cd thread-pool
cmake -B build -S . -DCMAKE_INSTALL_PREFIX=/usr/local -G Ninja
cmake --build build
cmake --install build # Note: may need `sudo` for system directories- In your
CMakeLists.txt:
find_package(thread-pool REQUIRED)
target_link_libraries(your-target PRIVATE thread-pool::thread-pool)In your CMakeLists.txt:
include(FetchContent)
FetchContent_Declare(
thread-pool
GIT_REPOSITORY https://github.com/Millforge/thread-pool.git
GIT_TAG main # This will always pull the latest code from the `main` branch. You may also use a specific release version or tag
)
FetchContent_MakeAvailable(thread-pool)
target_link_libraries(your-target PRIVATE thread-pool::thread-pool)In your CMakeLists.txt:
include(CPM.cmake) # ensure CPM.cmake is included
CPMAddPackage(
NAME thread-pool
GITHUB_REPOSITORY Millforge/thread-pool
GIT_TAG main # use a specific tag or commit for stability
)
target_link_libraries(your-target PRIVATE thread-pool::thread-pool)For more information on how to add CPM to your project, see the CPM documentation.
To uninstall the library, you can either manually remove the installed files or use the following script:
cmake --build build --target uninstallimport thread_pool;
#include <cstdio>
int main() {
// Use defaults: DefaultTask, DefaultQueue<DefaultTask>, DefaultPolicy, default allocator.
thread_pool::ThreadPool<> pool;
pool.set_thread_count(4); // Set number of worker threads
pool.submit([] noexcept {
// Some work. The callable must be `noexcept` and return `void` to satisfy the task concept.
std::printf("Hello from worker\n");
});
pool.stop().wait_for_tasks_completion(); // Request stop and wait for queued tasks to be processed
return 0;
}The project includes a test suite using GTest. To build and run the tests:
cmake -B build -S . -G Ninja -DTHREAD_POOL_BUILD_TESTS=ON
cmake --build build
ctest --test-dir buildMake sure you have GTest installed.
- ThreadPool class (API)
- AffinityThreadPool (API)
- Task concept & DefaultTask
- TaskQueue concepts & DefaultQueue
- Policy concepts & DefaultPolicy
The project includes Doxygen documentation for the API. If Doxygen is installed, you can build the documentation with:
cmake --build build --target thread-pool-docsThe generated documentation will be located at build/docs/html/index.html. Open this file in your web browser to view the API reference.
If Doxygen is not found, the documentation target will be skipped.
-
ThreadPool (template)
- Constructors
- Primary methods
submitset_thread_countthread_countstatusstopshutdownjoin_all_threadswait_for_tasks_completiontask_queueget_thread_allocator
- Destructor
-
AffinityThreadPool (template)
- Constructors
- Primary methods
startget_thread_referencejoin_all_threadsmax_thread_countthread_count
- Destructor
- The library relies on
noexceptguarantees and atomicwait/notify(C++20/C++23 primitives). - The
DefaultQueueusesstd::pmr::unsynchronized_pool_resourcefor memory efficiency — you can swap in a lock-free queue if needed. Policyhooks are optional; the pool checks for their presence via concepts and only calls them when available.
Contributions, issues, and feature requests are welcome! Please note:
- ✅ Maintain thread safety
- ✅ Follow existing code style and formatting
- ✅ Add tests for your changes
- ✅ Ensure all tests pass
- For major features, please open an issue first to discuss
- Update documentation as needed
Feel free to open an issue for any questions!