My Project 4.4.0
C++ Distributed Hash Table
Loading...
Searching...
No Matches
thread_pool.h
1// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
2// SPDX-License-Identifier: MIT
3#pragma once
4
5#include "def.h"
6
7#include <condition_variable>
8#include <vector>
9#include <queue>
10#include <future>
11#include <functional>
12
13#if __cplusplus < 202002L
14#include <ciso646>
15#endif
16
17namespace dht {
18
19class OPENDHT_PUBLIC ThreadPool
20{
21public:
22 static ThreadPool& computation();
23 static ThreadPool& io();
24
25 ThreadPool();
26 ThreadPool(unsigned minThreads, unsigned maxThreads = 0);
27 ~ThreadPool();
28
29 void run(std::function<void()>&& cb);
30
31 template<class T>
32 std::future<T> get(std::function<T()>&& cb)
33 {
34 auto ret = std::make_shared<std::promise<T>>();
35 run([cb = std::move(cb), ret]() mutable {
36 try {
37 ret->set_value(cb());
38 } catch (...) {
39 try {
40 ret->set_exception(std::current_exception());
41 } catch (...) {
42 }
43 }
44 });
45 return ret->get_future();
46 }
47 template<class T>
48 std::shared_future<T> getShared(std::function<T()>&& cb)
49 {
50 return get(std::move(cb));
51 }
52
53 void stop(bool wait = true);
54 void join();
55 void detach();
56
57private:
58 std::mutex lock_;
59 std::condition_variable cv_ {};
60 std::condition_variable stopCv_ {};
61 std::queue<std::function<void()>> tasks_ {};
62 std::vector<std::unique_ptr<std::thread>> threads_;
63 unsigned readyThreads_ {0};
64 bool running_ {true};
65 bool stopping_ {false};
66
67 unsigned minThreads_;
68 const unsigned maxThreads_;
69 std::chrono::steady_clock::duration threadExpirationDelay {std::chrono::minutes(5)};
70 double threadDelayRatio_ {2};
71
72 void threadEnded(std::thread&);
73};
74
75class OPENDHT_PUBLIC Executor : public std::enable_shared_from_this<Executor>
76{
77public:
78 Executor(ThreadPool& pool, unsigned maxConcurrent = 1)
79 : threadPool_(pool)
80 , maxConcurrent_(maxConcurrent)
81 {}
82
83 void run(std::function<void()>&& task);
84
85private:
86 std::reference_wrapper<ThreadPool> threadPool_;
87 const unsigned maxConcurrent_ {1};
88 std::mutex lock_;
89 unsigned current_ {0};
90 std::queue<std::function<void()>> tasks_ {};
91
92 void run_(std::function<void()>&& task);
93 void schedule();
94};
95
96class OPENDHT_PUBLIC ExecutionContext
97{
98public:
99 ExecutionContext(ThreadPool& pool)
100 : threadPool_(pool)
101 , state_(std::make_shared<SharedState>())
102 {}
103
104 ~ExecutionContext() { state_->destroy(); }
105
107 void stop() { state_->destroy(false); }
108
109 void run(std::function<void()>&& task)
110 {
111 std::lock_guard lock(state_->mtx);
112 if (state_->shutdown_)
113 return;
114 state_->pendingTasks++;
115 threadPool_.get().run([task = std::move(task), state = state_] { state->run(task); });
116 }
117
118private:
119 struct SharedState
120 {
121 std::mutex mtx;
122 std::condition_variable cv {};
123 unsigned pendingTasks {0};
124 unsigned ongoingTasks {0};
126 bool shutdown_ {false};
128 std::atomic_bool destroyed {false};
129
130 void destroy(bool wait = true)
131 {
132 std::unique_lock lock(mtx);
133 if (destroyed)
134 return;
135 if (wait) {
136 cv.wait(lock, [this] { return pendingTasks == 0 && ongoingTasks == 0; });
137 }
138 shutdown_ = true;
139 if (not wait) {
140 cv.wait(lock, [this] { return ongoingTasks == 0; });
141 }
142 destroyed = true;
143 }
144
145 void run(const std::function<void()>& task)
146 {
147 {
148 std::lock_guard lock(mtx);
149 pendingTasks--;
150 ongoingTasks++;
151 }
152 if (destroyed)
153 return;
154 task();
155 {
156 std::lock_guard lock(mtx);
157 ongoingTasks--;
158 cv.notify_all();
159 }
160 }
161 };
162 std::reference_wrapper<ThreadPool> threadPool_;
163 std::shared_ptr<SharedState> state_;
164};
165
166} // namespace dht