Ginger 1.1.9
Loading...
Searching...
No Matches
thread_pool.hpp
Go to the documentation of this file.
1#pragma once
2
23#include <condition_variable>
24#include <functional>
25#include <future>
26#include <memory>
27#include <mutex>
28#include <queue>
29#include <thread>
30#include <type_traits>
31#include <utility>
32
33namespace ginger {
34
36 public:
42 explicit thread_pool(size_t num_threads = std::thread::hardware_concurrency()) {
43 if (num_threads == 0) {
44 num_threads = 1;
45 }
46 workers_.reserve(num_threads);
47 for (size_t i = 0; i < num_threads; ++i) {
48 workers_.emplace_back([this] { worker_loop(); });
49 }
50 }
51
53 {
54 std::lock_guard<std::mutex> lock(queue_mutex_);
55 stop_ = true;
56 }
57 condition_.notify_all();
58 for (auto& w : workers_) {
59 if (w.joinable()) {
60 w.join();
61 }
62 }
63 }
64
65 [[nodiscard]] auto size() const -> size_t { return workers_.size(); }
66
67 thread_pool(const thread_pool&) = delete;
71
79 template <typename F> auto enqueue(F&& task)
80 -> std::future<std::invoke_result_t<std::decay_t<F>>> {
81 using return_type = std::invoke_result_t<std::decay_t<F>>;
82
83 auto packaged
84 = std::make_shared<std::packaged_task<return_type()>>(std::forward<F>(task));
85
86 auto future = packaged->get_future();
87 {
88 std::lock_guard<std::mutex> lock(queue_mutex_);
89 if (stop_) {
90 throw std::runtime_error("enqueue on stopped thread_pool");
91 }
92 tasks_.emplace([packaged]() { (*packaged)(); });
93 }
94 condition_.notify_one();
95 return future;
96 }
97
98 private:
99 void worker_loop() {
100 while (true) {
101 std::function<void()> task;
102 {
103 std::unique_lock<std::mutex> lock(queue_mutex_);
104 condition_.wait(lock, [this] { return stop_ || !tasks_.empty(); });
105 if (stop_ && tasks_.empty()) {
106 return;
107 }
108 task = std::move(tasks_.front());
109 tasks_.pop();
110 }
111 task();
112 }
113 }
114
115 std::vector<std::thread> workers_;
116 std::queue<std::function<void()>> tasks_;
117 std::mutex queue_mutex_;
118 std::condition_variable condition_;
119 bool stop_{};
120 };
121
130 inline auto get_thread_pool() -> thread_pool& {
131 static thread_pool pool(std::thread::hardware_concurrency());
132 return pool;
133 }
134
135} // namespace ginger
constexpr auto make_vdc_table() -> std::array< double, N >
Helper to generate a constexpr table of VdCorput<Base> values.
Definition aberth.hpp:21
Definition thread_pool.hpp:35
thread_pool & operator=(thread_pool &&)=delete
~thread_pool()
Definition thread_pool.hpp:52
thread_pool(size_t num_threads=std::thread::hardware_concurrency())
Construct a thread pool with the given number of worker threads.
Definition thread_pool.hpp:42
thread_pool(thread_pool &&)=delete
thread_pool & operator=(const thread_pool &)=delete
auto enqueue(F &&task) -> std::future< std::invoke_result_t< std::decay_t< F > > >
Definition thread_pool.hpp:79
thread_pool(const thread_pool &)=delete
auto size() const -> size_t
Definition thread_pool.hpp:65
Options for convergence-based algorithms.
Definition aberth.hpp:13
auto get_thread_pool() -> thread_pool &
Convenience accessor returning a singleton thread pool.
Definition thread_pool.hpp:130