join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
thread_pool.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_CORE_THREAD_POOL_HPP
26#define JOIN_CORE_THREAD_POOL_HPP
27
28// libjoin.
29#include <join/condition.hpp>
30#include <join/thread.hpp>
31#include <join/cpu.hpp>
32
33// C++.
34#include <functional>
35#include <memory>
36#include <vector>
37#include <deque>
38
39namespace join
40{
42 class ThreadPool;
43
48 {
49 private:
55
56 public:
61 WorkerThread (const WorkerThread& other) = delete;
62
68 WorkerThread& operator= (const WorkerThread& other) = delete;
69
74 WorkerThread (WorkerThread&& other) = delete;
75
82
86 ~WorkerThread () noexcept;
87
88 private:
92 void work ();
93
95 ThreadPool* _pool = nullptr;
96
98 Thread _thread;
99
101 friend class ThreadPool;
102 };
103
108 {
109 public:
114 ThreadPool (int workers = int (CpuTopology::instance ()->cores ().size ()));
115
120 ThreadPool (const ThreadPool& other) = delete;
121
127 ThreadPool& operator= (const ThreadPool& other) = delete;
128
133 ThreadPool (ThreadPool&& other) = delete;
134
140 ThreadPool& operator= (ThreadPool&& other) = delete;
141
145 ~ThreadPool () noexcept;
146
152 template <class Function, class... Args>
153 void push (Function&& func, Args&&... args)
154 {
155 ScopedLock<Mutex> lock (_mutex);
156 _jobs.emplace_back (std::bind (std::forward<Function> (func), std::forward<Args> (args)...));
157 _condition.signal ();
158 }
159
163 size_t size () const noexcept;
164
165 private:
167 std::vector<std::unique_ptr<WorkerThread>> _workers;
168
170 Condition _condition;
171
173 Mutex _mutex;
174
176 bool _stop = false;
177
179 std::deque<std::function<void ()>> _jobs;
180
182 friend class WorkerThread;
183 };
184
191 template <class InputIt, class Func>
192 void distribute (InputIt first, InputIt last, Func function)
193 {
194 // check if we have tasks to perform.
195 int count = std::distance (first, last);
196 if (count)
197 {
198 // determine number of threads and tasks per thread to run.
199 int concurrency = int (CpuTopology::instance ()->cores ().size ());
200 // no need to create more threads than tasks.
201 concurrency = std::min (concurrency, count);
202 int elements = count / concurrency;
203 int rest = count % concurrency;
204 // distribute tasks to threads.
205 std::vector<int> tasks (concurrency, elements);
206 for (int i = 0; i < rest; ++i)
207 {
208 ++tasks[i];
209 }
210
211 // determine the real thread pool size (concurrency minus 1 as we are a thread).
212 std::vector<Thread> pool;
213 int nth = concurrency - 1;
214 pool.reserve (nth);
215
216 // create threads.
217 auto beg = first, end = first;
218 for (int i = 0; i < nth; ++i)
219 {
220 std::advance (end, tasks[i]);
221 pool.emplace_back (function, beg, end);
222 beg = end;
223 }
224
225 // we are a thread so we can help.
226 function (beg, last);
227
228 // wait for threads to terminate.
229 for (auto& thread : pool)
230 {
231 thread.join ();
232 }
233 }
234 }
235
242 template <class InputIt, class Func>
243 void parallelForEach (InputIt first, InputIt last, Func function)
244 {
245 distribute (first, last, [&function] (InputIt beg, InputIt end) {
246 for (; beg != end; ++beg)
247 {
248 function (*beg);
249 }
250 });
251 }
252}
253
254#endif
condition variable class.
Definition condition.hpp:42
static const CpuTopology * instance()
get instance.
Definition cpu.cpp:49
fixed-capacity move-only allocation-free alternative to std::function.
Definition function.hpp:44
class used to protect shared data from being simultaneously accessed by multiple threads.
Definition mutex.hpp:37
class owning a mutex for the duration of a scoped block.
Definition mutex.hpp:249
thread pool class.
Definition thread_pool.hpp:108
ThreadPool(ThreadPool &&other)=delete
move constructor.
ThreadPool(const ThreadPool &other)=delete
copy constructor.
thread class.
Definition thread.hpp:180
worker thread class.
Definition thread_pool.hpp:48
WorkerThread & operator=(const WorkerThread &other)=delete
copy assignment.
friend class ThreadPool
friendship with ThreadPool.
Definition thread_pool.hpp:101
WorkerThread(WorkerThread &&other)=delete
move constructor.
~WorkerThread() noexcept
destroy worker thread.
Definition thread_pool.cpp:47
WorkerThread(const WorkerThread &other)=delete
copy constructor.
Definition acceptor.hpp:32
void distribute(InputIt first, InputIt last, Func function)
determine the number of threads and tasks per thread to run and execute them in parallel.
Definition thread_pool.hpp:192
void parallelForEach(InputIt first, InputIt last, Func function)
parallel for each loop.
Definition thread_pool.hpp:243
Definition error.hpp:144