14# if __has_include(<version>)
24#ifdef __cpp_lib_move_only_function
32 typename ThreadType = std::jthread>
33 requires std::invocable<FunctionType> &&
34 std::is_same_v<void, std::invoke_result_t<FunctionType>>
38 const unsigned int &number_of_threads = std::thread::hardware_concurrency())
39 : tasks_(number_of_threads) {
40 std::size_t current_id = 0;
41 for (std::size_t i = 0; i < number_of_threads; ++i) {
42 priority_queue_.
push_back(
size_t(current_id));
44 threads_.emplace_back([&,
id = current_id](
const std::stop_token &stop_tok) {
47 tasks_[id].signal.acquire();
51 while (
auto task = tasks_[
id].tasks.pop_front()) {
53 pending_tasks_.fetch_sub(1, std::memory_order_release);
54 std::invoke(std::move(task.value()));
60 for (std::size_t j = 1; j < tasks_.size(); ++j) {
61 const std::size_t index = (
id + j) % tasks_.size();
62 if (
auto task = tasks_[index].tasks.steal()) {
64 pending_tasks_.fetch_sub(1, std::memory_order_release);
65 std::invoke(std::move(task.value()));
71 }
while (pending_tasks_.load(std::memory_order_acquire) > 0);
75 }
while (!stop_tok.stop_requested());
87 std::ignore = priority_queue_.
pop_back();
94 for (std::size_t i = 0; i < threads_.size(); ++i) {
95 threads_[i].request_stop();
96 tasks_[i].signal.release();
115 template <
typename Function,
typename... Args,
116 typename ReturnType = std::invoke_result_t<Function &&, Args &&...>>
117 requires std::invocable<Function, Args...>
118 [[nodiscard]] std::future<ReturnType>
enqueue(Function f, Args... args) {
119#if __cpp_lib_move_only_function
121 std::promise<ReturnType> promise;
122 auto future = promise.get_future();
123 auto task = [func = std::move(f), ... largs = std::move(args),
124 promise = std::move(promise)]()
mutable {
126 if constexpr (std::is_same_v<ReturnType, void>) {
130 promise.set_value(func(largs...));
133 promise.set_exception(std::current_exception());
136 enqueue_task(std::move(task));
149 auto shared_promise = std::make_shared<std::promise<ReturnType>>();
150 auto task = [func = std::move(f), ... largs = std::move(args),
151 promise = shared_promise]() {
153 if constexpr (std::is_same_v<ReturnType, void>) {
155 promise->set_value();
157 promise->set_value(func(largs...));
161 promise->set_exception(std::current_exception());
166 auto future = shared_promise->get_future();
168 enqueue_task(std::move(task));
180 template <
typename Function,
typename... Args>
181 requires std::invocable<Function, Args...> &&
182 std::is_same_v<void, std::invoke_result_t<Function &&, Args &&...>>
185 std::move([f = std::forward<Function>(func),
186 ... largs = std::forward<Args>(args)]()
mutable ->
decltype(
auto) {
189 std::invoke(f, largs...);
195 [[nodiscard]]
auto size()
const {
return threads_.size(); }
198 template <
typename Function>
199 void enqueue_task(Function &&f) {
200 auto i_opt = priority_queue_.copy_front_and_rotate_to_back();
201 if (!i_opt.has_value()) {
206 pending_tasks_.fetch_add(1, std::memory_order_relaxed);
207 tasks_[i].tasks.push_back(std::forward<Function>(f));
208 tasks_[i].signal.release();
213 std::binary_semaphore signal{0};
216 std::vector<ThreadType> threads_;
217 std::deque<task_item> tasks_;
219 std::atomic_int_fast64_t pending_tasks_{};
Definition thread_pool.h:35
~thread_pool()
Definition thread_pool.h:92
auto size() const
Definition thread_pool.h:195
std::future< ReturnType > enqueue(Function f, Args... args)
Enqueue a task into the thread pool that returns a result.
Definition thread_pool.h:118
void enqueue_detach(Function &&func, Args &&...args)
Enqueue a task to be executed in the thread pool that returns void.
Definition thread_pool.h:183
thread_pool & operator=(const thread_pool &)=delete
thread_pool(const thread_pool &)=delete
thread pool is non-copyable
thread_pool(const unsigned int &number_of_threads=std::thread::hardware_concurrency())
Definition thread_pool.h:37
Definition thread_safe_queue.h:25
void push_back(T &&value)
Definition thread_safe_queue.h:32
std::optional< T > pop_back()
Definition thread_safe_queue.h:56
void rotate_to_front(const T &item)
Definition thread_safe_queue.h:74
std::function< void()> default_function_type
Definition thread_pool.h:27
Definition thread_pool.h:21