Toast Engine
Loading...
Searching...
No Matches
thread_pool.hpp
Go to the documentation of this file.
1
7#pragma once
8#include <atomic>
9#include <cassert>
10#include <condition_variable>
11#include <functional>
12#include <future>
13#include <memory>
14#include <queue>
15#include <thread>
16#include <toast/export.hpp>
17#include <type_traits>
18#include <utility>
19#include <vector>
20
21namespace toast {
22
48class TOAST_API ThreadPool {
49public:
59 static auto create() noexcept -> std::unique_ptr<ThreadPool>;
60
76 template<typename T>
77 static auto push(T&& job) -> std::future<std::invoke_result_t<T>>;
78
80 static void pushRaw(std::move_only_function<void()>&& job);
81
90 void destroy();
91
100 [[nodiscard]] [[deprecated("Use waitIdle() instead")]]
101 auto busy() -> bool;
102
109 void waitIdle();
110
111 static auto workerCount() -> size_t;
112
114 [[nodiscard]]
115 static auto idleWorkers() noexcept -> size_t;
116
118 [[nodiscard]]
119 static auto onWorkerThread() noexcept -> bool;
120
121 // No copy and move constructors
122 ThreadPool(ThreadPool&) = delete;
123 ThreadPool(ThreadPool&&) = delete;
124 auto operator=(const ThreadPool&) -> ThreadPool& = delete;
125 auto operator=(ThreadPool&&) -> ThreadPool& = delete;
126
127 ~ThreadPool() {
128 waitIdle();
129 destroy();
130 }
131
132private:
133 ThreadPool();
134 inline static ThreadPool* instance = nullptr;
135 static auto get() noexcept -> ThreadPool&;
136
137 void threadLoop();
138 static void enqueue(std::move_only_function<void()>&& job);
139
140 struct {
141 bool should_stop = false;
142 std::atomic<int> active_jobs = 0;
143 std::atomic<int> idle_workers = 0;
144 std::mutex queue_mutex;
145 std::condition_variable job_available;
146 std::condition_variable all_done;
147 std::vector<std::jthread> workers;
148 std::queue<std::move_only_function<void()>> jobs;
149 } m;
150};
151
152template<typename T>
153auto ThreadPool::push(T&& job) -> std::future<std::invoke_result_t<T>> {
154 using result_t = std::invoke_result_t<T>;
155
156 std::packaged_task<result_t()> task(std::forward<T>(job));
157 auto future = task.get_future();
158 enqueue([task = std::move(task)]() mutable { task(); });
159 return future;
160}
161
162}
static void pushRaw(std::move_only_function< void()> &&job)
Queues a job with no std::future the caller synchronizes completion itself same queue and workers as ...
Definition thread_pool.cpp:17
std::condition_variable all_done
Notified when activeJobs hits 0 and queue is empty.
Definition thread_pool.hpp:146
auto busy() -> bool
Checks if the pool has pending or in-flight jobs.
Definition thread_pool.cpp:49
static auto push(T &&job) -> std::future< std::invoke_result_t< T > >
Queues a job for execution by a worker thread.
Definition thread_pool.hpp:153
void waitIdle()
Blocks the calling thread until all queued and active jobs complete.
Definition thread_pool.cpp:54
std::atomic< int > idle_workers
Number of workers waiting for a job.
Definition thread_pool.hpp:143
std::queue< std::move_only_function< void()> > jobs
Pending job queue.
Definition thread_pool.hpp:148
bool should_stop
Flag to signal workers to stop.
Definition thread_pool.hpp:141
std::mutex queue_mutex
Mutex protecting the job queue.
Definition thread_pool.hpp:144
static auto create() noexcept -> std::unique_ptr< ThreadPool >
Initializes the pool and returns a pointer with ownership.
Definition thread_pool.cpp:116
static auto onWorkerThread() noexcept -> bool
Definition thread_pool.cpp:63
std::atomic< int > active_jobs
Number of jobs currently executing.
Definition thread_pool.hpp:142
std::condition_variable job_available
Notified when a job is enqueued or stop is requested.
Definition thread_pool.hpp:145
static auto idleWorkers() noexcept -> size_t
Definition thread_pool.cpp:71
void destroy()
Destroys the thread pool and waits for all workers to finish.
Definition thread_pool.cpp:32
std::vector< std::jthread > workers
Worker threads (auto-join on destruction).
Definition thread_pool.hpp:147