{"id":15047521,"url":"https://github.com/alugowski/task-thread-pool","last_synced_at":"2025-04-10T00:51:09.790Z","repository":{"id":166709931,"uuid":"642217237","full_name":"alugowski/task-thread-pool","owner":"alugowski","description":"Fast and lightweight thread pool for C++11 and newer.","archived":false,"fork":false,"pushed_at":"2024-11-18T04:21:08.000Z","size":56,"stargazers_count":42,"open_issues_count":1,"forks_count":3,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-10T00:51:04.501Z","etag":null,"topics":["async","asynchronous","asynchronous-programming","asynchronous-tasks","concurrency","concurrent-programming","cpp11","cpp14","cpp17","cpp20","cpp23","multithreading","parallel","task-queue","task-runner","thread-pool","threadpool","threads"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alugowski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-BSD.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-18T04:39:01.000Z","updated_at":"2025-03-22T14:41:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"8f1b10d9-4ad4-474a-88da-7fcaa7818b3e","html_url":"https://github.com/alugowski/task-thread-pool","commit_stats":{"total_commits":39,"total_committers":2,"mean_commits":19.5,"dds":0.02564102564102566,"last_synced_commit":"0ad92b3ca55ad4fac81396090f073e266d25879e"},"previous_names":["alugowski/task_thread_pool"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alugowski%2Ftask-thread-pool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alugowski%2Ftask-thread-pool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alugowski%2Ftask-thread-pool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alugowski%2Ftask-thread-pool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alugowski","download_url":"https://codeload.github.com/alugowski/task-thread-pool/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248137997,"owners_count":21053775,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","asynchronous","asynchronous-programming","asynchronous-tasks","concurrency","concurrent-programming","cpp11","cpp14","cpp17","cpp20","cpp23","multithreading","parallel","task-queue","task-runner","thread-pool","threadpool","threads"],"created_at":"2024-09-24T20:59:38.636Z","updated_at":"2025-04-10T00:51:09.743Z","avatar_url":"https://github.com/alugowski.png","language":"C++","readme":"[![tests](https://github.com/alugowski/task-thread-pool/actions/workflows/tests.yml/badge.svg)](https://github.com/alugowski/task-thread-pool/actions/workflows/tests.yml)\n[![codecov](https://codecov.io/gh/alugowski/task-thread-pool/branch/main/graph/badge.svg?token=M9J4azRYyI)](https://codecov.io/gh/alugowski/task-thread-pool)\n![File size in bytes](https://img.shields.io/github/size/alugowski/task-thread-pool/include/task_thread_pool.hpp)\n[![License](https://img.shields.io/badge/License-BSD_2--Clause-orange.svg)](https://opensource.org/licenses/BSD-2-Clause)\n[![License](https://img.shields.io/badge/License-Boost_1.0-lightblue.svg)](https://www.boost.org/LICENSE_1_0.txt)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n`task-thread-pool` is a fast and lightweight thread pool for C++11 and newer.\n\nEasily add parallelism to your project without introducing heavy dependencies.\n\n* Focus on correctness, ease of use, simplicity, performance.\n* [Small single header file](https://raw.githubusercontent.com/alugowski/task-thread-pool/main/include/task_thread_pool.hpp) and permissive licensing means easy integration.\n* Tested on all major platforms and compilers:\n  * Linux, macOS, Windows\n  * GCC, LLVM/Clang, MSVC, MinGW, Emscripten\n    * CI tests on GCC 7+ and LLVM 7+, should work on older\n  * C++11, C++14, C++17, C++20, C++23\n* Comprehensive test suite, including stress tests.\n* Benchmarks help confirm good performance.\n\n# Usage\n\n```c++\n#include \u003ctask_thread_pool.hpp\u003e\n```\n\n```c++\ntask_thread_pool::task_thread_pool pool; // num_threads = number of physical cores\n// or\ntask_thread_pool::task_thread_pool pool{4}; // num_threads = 4\n```\n\nSubmit a function, a lambda, `std::packaged_task`, `std::function`, or any [*Callable*](https://en.cppreference.com/w/cpp/named_req/Callable), and its arguments:\n\n```c++\npool.submit_detach( [](int arg) { std::cout \u003c\u003c arg; }, 123456 );\n```\n\nTo track task return values (and thrown exceptions), use `submit()` which returns an [`std::future`](https://en.cppreference.com/w/cpp/thread/future):\n\n```c++\nstd::future\u003cint\u003e future = pool.submit([] { return 1; });\n\nint result = future.get(); // returns 1\n```\n`std::future::get()` waits for the task to complete.\n\nTo wait for all tasks to complete:\n```c++\npool.wait_for_tasks();\n```\n\n## Parallel Loops and More\n\nUse [poolSTL](https://github.com/alugowski/poolSTL) to parallelize loops, transforms, sorts, and other standard library algorithms using this thread pool.\nThis approach is easy to start with and also keeps your code future-proof by employing standard C++ mechanisms.\nIt is easy to later change parallelism libraries (or start using the compiler-provided ones, once they're available to you).\n\nFor example, use [std::for_each](https://en.cppreference.com/w/cpp/algorithm/for_each) to parallelize `for` and `for-each` loops:\n\n```c++\nstd::vector\u003cint\u003e v = {0, 1, 2, 3, 4, 5};\ntask_thread_pool::task_thread_pool pool;\n\n// parallel for\nusing poolstl::iota_iter;\n\nstd::for_each(poolstl::par.on(pool), iota_iter\u003cint\u003e(0), iota_iter\u003cint\u003e(v.size()), [](int i) {\n    std::cout \u003c\u003c v[i];  // loop body\n});\n\n// parallel for-each\nstd::for_each(poolstl::par.on(pool), v.cbegin(), v.cend(), [](auto value) {\n    std::cout \u003c\u003c value;  // loop body\n});\n```\n\n# Example\n\n```c++\n#include \u003ciostream\u003e\n// Use #include \"task_thread_pool.hpp\" for relative path,\n// and #include \u003ctask_thread_pool.hpp\u003e if installed in include path\n#include \"task_thread_pool.hpp\"\n\nint sum(int a, int b) { return a + b; }\n\nint main() {\n    // Create a thread pool. The number of threads is equal to the number of cores in the system,\n    // as given by std::thread::hardware_concurrency().\n    // You can also specify the number of threads, like so: pool(4),\n    // or resize the thread pool later using pool.set_num_threads(4).\n    task_thread_pool::task_thread_pool pool;\n\n    //---------------------------------------------\n    // Submit a task that returns a value.\n    std::future\u003cint\u003e one_future = pool.submit([] { return 1; });\n    // Use std::future::get() to wait for the task to complete and return the value.\n    std::cout \u003c\u003c \"Task returned: \" \u003c\u003c one_future.get() \u003c\u003c std::endl;\n\n    //---------------------------------------------\n    // Tasks may have arguments:\n    std::future\u003cint\u003e sum_future = pool.submit(\u0026sum, 1, 2);\n    std::cout \u003c\u003c \"Sum = \" \u003c\u003c sum_future.get() \u003c\u003c std::endl;\n\n    //---------------------------------------------\n    // Submit a task that we don't need to track the execution of:\n    pool.submit_detach([](int arg) {\n        std::cout \u003c\u003c \"The argument is: \" \u003c\u003c arg \u003c\u003c std::endl;\n    }, 42);\n\n    //---------------------------------------------\n    // Wait for all tasks to complete:\n    pool.wait_for_tasks();\n\n    //---------------------------------------------\n    // The pool can be paused:\n    pool.pause();\n\n    // Submit a task that won't be started until the pool is unpaused.\n    std::future\u003cvoid\u003e paused_future = pool.submit([] {\n        std::cout \u003c\u003c \"Paused task executes\" \u003c\u003c std::endl;\n    });\n\n    // prints 1\n    std::cout \u003c\u003c \"Number of tasks in the pool: \" \u003c\u003c pool.get_num_tasks() \u003c\u003c std::endl;\n    \n    // Resume executing queued tasks.\n    pool.unpause();\n\n    // Wait for the task to finish.\n    paused_future.get();\n\n    // prints 0\n    std::cout \u003c\u003c \"Number of tasks in the pool: \" \u003c\u003c pool.get_num_tasks() \u003c\u003c std::endl;\n\n    //---------------------------------------------\n    // All queued tasks are executed before the pool is destroyed:\n    pool.submit_detach([]{\n        std::cout \u003c\u003c \"One last task\" \u003c\u003c std::endl;\n    });\n\n    return 0;\n}\n```\n\n\n# Installation\n\n\n### Copy\n`task-thread-pool` is a single header file.\n\nYou may simply copy [task_thread_pool.hpp](https://raw.githubusercontent.com/alugowski/task-thread-pool/main/include/task_thread_pool.hpp) into your project or your system `include/`.\n\n### CMake\n\nYou may use CMake to fetch directly from GitHub:\n```cmake\ninclude(FetchContent)\nFetchContent_Declare(\n        task-thread-pool\n        GIT_REPOSITORY https://github.com/alugowski/task-thread-pool\n        GIT_TAG main\n        GIT_SHALLOW TRUE\n)\nFetchContent_MakeAvailable(task-thread-pool)\n\ntarget_link_libraries(YOUR_TARGET task-thread-pool::task-thread-pool)\n```\n\nUse `GIT_TAG main` to use the latest version, or replace `main` with a version number to pin a fixed version.\n\n### vcpkg\n\n```\nvcpkg install task-thread-pool\n```\n\n### Note for Clang and GCC \u003c9 users\nSome compilers, including non-Apple Clang and GCC 8 and older, require the `-lpthread` linker flag to use C++11 threads. The above CMake instructions will do that automatically.\n\n# How it works\n\nSimplicity is a major goal so this thread pool does what you'd expect. Submitted tasks are added to a queue\nand worker threads pull from this queue.\n\nCare is taken that this process is efficient. The `submit` methods are optimized to only do what they need. Worker threads only lock the queue once per task. Excess synchronization is avoided.\n\nThat said, this simple design is best used in low contention scenarios. If you have many tiny tasks or many (10+) physical CPU cores then this single queue becomes a hotspot. In that case avoid lightweight pools like this one and use something like Threading Building Blocks. They include work-stealing executors that avoid this hotspot at the cost of extra complexity and project dependencies.\n\n# Benchmarking\n\nWe include some Google Benchmarks for some pool operations in [benchmark/](benchmark).\n\nIf there is an operation you care about feel free to open an issue or submit your own benchmark code.\n\n```\n-------------------------------------------------------------------------------\nBenchmark                                     Time             CPU   Iterations\n-------------------------------------------------------------------------------\npool_create_destroy                       46318 ns        26004 ns        26489\nsubmit_detach_packaged_task/paused:1        254 ns          244 ns      2875157\nsubmit_detach_packaged_task/paused:0        362 ns          304 ns      2296008\nsubmit_detach_void_lambda/paused:1          263 ns          260 ns      3072412\nsubmit_detach_void_lambda/paused:0          418 ns          374 ns      2020779\nsubmit_void_lambda/paused:1                 399 ns          385 ns      1942879\nsubmit_void_lambda/paused:0                 667 ns          543 ns      1257161\nsubmit_void_lambda_future/paused:1          391 ns          376 ns      1897255\nsubmit_void_lambda_future/paused:0          649 ns          524 ns      1238653\nsubmit_int_lambda_future/paused:1           395 ns          376 ns      1902789\nsubmit_int_lambda_future/paused:0           643 ns          518 ns      1146038\nrun_1k_packaged_tasks                    462965 ns       362080 ns         1939\nrun_1k_void_lambdas                      492022 ns       411069 ns         1712\nrun_1k_int_lambdas                       679579 ns       533813 ns         1368\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falugowski%2Ftask-thread-pool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falugowski%2Ftask-thread-pool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falugowski%2Ftask-thread-pool/lists"}