VoxelEngine
 
Loading...
Searching...
No Matches
ThreadPool.h
1#pragma once
2
3#include <atomic>
4#include <concepts>
5#include <future>
6#include <memory>
7#include <queue>
8#include <vector>
9
10#include <functional>
11
12#include <condition_variable>
13#include <mutex>
14#include <thread>
15
16#ifdef _WIN32
17#define NOMINMAX
18#define NOGDI
19#include <windows.h>
20#endif
21
22using Job = std::function<void()>;
24 public:
25 ThreadPool(int n) {
26 if (n == 0)
27 throw std::runtime_error("Thread pool thread count is 0!");
28
29 for (int i = 0; i < n; ++i)
30 m_threads.emplace_back(std::thread(&ThreadPool::loop, this));
31 }
32 ~ThreadPool() { stop(); }
33
34 void add(Job&& job) {
35 // clang-format off
36 {
37 std::unique_lock lock(m_mutex);
38 m_jobs.push(std::move(job));
39 }
40 m_cv.notify_one(); // Notifying only one because only one job is added so
41 // only one thread can be working on it?
42 // clang-format on
43 }
44
45 std::future<void> addBatch(std::vector<Job> batch) {
46 auto promise = std::make_shared<std::promise<void>>();
47 auto remainingJobs = std::make_shared<std::atomic<size_t>>(batch.size());
48 std::future<void> future = promise->get_future();
49
50 for (const auto& job : batch) {
51 add([job = std::move(job), promise, remainingJobs]() {
52 job();
53
54 if (remainingJobs->fetch_sub(1) == 1) {
55 promise->set_value();
56 }
57 });
58 }
59
60 if (batch.size() == 0) {
61 promise->set_value();
62 }
63
64 return future;
65 }
66
67 void stop() {
68 {
69 std::unique_lock lock(m_mutex);
70 m_terminate = true;
71 }
72 m_cv.notify_all();
73
74 for (auto& t : m_threads) {
75 t.join();
76 }
77 m_threads.clear();
78 }
79
80 void resume() { m_pause = false; }
81
82 void pause() { m_pause = true; }
83
84 private:
85 void loop() {
86#ifdef _WIN32
87 SetThreadDescription(GetCurrentThread(), L"ThreadPool");
88#endif
89 while (true) {
90 Job job;
91 {
92 std::unique_lock lock(m_mutex);
93 m_cv.wait(lock, [this] { return !m_jobs.empty() || m_terminate || m_pause; });
94
95 if (m_terminate) {
96 break;
97 }
98
99 if (m_jobs.empty()) {
100 continue;
101 }
102
103 job = m_jobs.front();
104 m_jobs.pop();
105 }
106 job();
107 }
108 }
109 bool m_terminate = false;
110 bool m_pause = false;
111 std::condition_variable m_cv;
112 std::mutex m_mutex;
113
114 std::vector<std::thread> m_threads;
115 std::queue<Job> m_jobs;
116};
Definition ThreadPool.h:23