Thread System 0.3.1
High-performance C++20 thread pool with work stealing and DAG scheduling
Loading...
Searching...
No Matches
future_extensions.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2024, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
5#pragma once
6
17#include <future>
18#include <memory>
19#include <chrono>
20#include <functional>
21
22namespace kcenon::thread {
23
30 template<typename T>
32 public:
33 using value_type = T;
34
38 explicit pool_future(std::future<T>&& future)
39 : future_(std::move(future)) {}
40
44 bool is_ready() const {
45 return future_.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
46 }
47
51 T get() {
52 return future_.get();
53 }
54
58 template<typename Rep, typename Period>
59 std::future_status wait_for(const std::chrono::duration<Rep, Period>& timeout) {
60 return future_.wait_for(timeout);
61 }
62
66 void wait() {
67 future_.wait();
68 }
69
73 bool valid() const {
74 return future_.valid();
75 }
76
80 template<typename F>
81 auto then(F&& continuation) -> pool_future<std::invoke_result_t<F, T>>;
82
83 private:
84 std::future<T> future_;
85 };
86
90 template<typename T>
92 public:
93 using value_type = T;
94
98 pool_promise() = default;
99
104 return pool_future<T>{promise_.get_future()};
105 }
106
110 void set_value(const T& value) {
111 promise_.set_value(value);
112 }
113
117 void set_value(T&& value) {
118 promise_.set_value(std::move(value));
119 }
120
124 void set_exception(std::exception_ptr exception) {
125 promise_.set_exception(exception);
126 }
127
131 void set_value_at_thread_exit(const T& value) {
132 promise_.set_value_at_thread_exit(value);
133 }
134
138 void set_exception_at_thread_exit(std::exception_ptr exception) {
139 promise_.set_exception_at_thread_exit(exception);
140 }
141
142 private:
143 std::promise<T> promise_;
144 };
145
149 template<>
150 class pool_promise<void> {
151 public:
153 return pool_future<void>{promise_.get_future()};
154 }
155
156 void set_value() {
157 promise_.set_value();
158 }
159
160 void set_exception(std::exception_ptr exception) {
161 promise_.set_exception(exception);
162 }
163
165 promise_.set_value_at_thread_exit();
166 }
167
168 void set_exception_at_thread_exit(std::exception_ptr exception) {
169 promise_.set_exception_at_thread_exit(exception);
170 }
171
172 private:
173 std::promise<void> promise_;
174 };
175
179 template<typename T>
182 auto future = promise.get_future();
183 promise.set_value(std::forward<T>(value));
184 return future;
185 }
186
191 pool_promise<void> promise;
192 auto future = promise.get_future();
193 promise.set_value();
194 return future;
195 }
196
200 template<typename T>
201 pool_future<T> make_exceptional_future(std::exception_ptr exception) {
202 pool_promise<T> promise;
203 auto future = promise.get_future();
204 promise.set_exception(exception);
205 return future;
206 }
207
211 template<typename... Futures>
212 void wait_for_all(Futures&... futures) {
213 (futures.wait(), ...);
214 }
215
219 template<typename... Futures>
220 size_t wait_for_any(Futures&... futures) {
221 // Use short timeout-based polling instead of busy-wait
222 // This significantly reduces CPU usage while maintaining responsiveness
223 constexpr auto poll_interval = std::chrono::microseconds(100);
224
225 size_t index = 0;
226 auto check_future = [&](auto& future) {
227 if (future.is_ready()) {
228 return true;
229 }
230 ++index;
231 return false;
232 };
233
234 while (true) {
235 index = 0;
236 if ((check_future(futures) || ...)) {
237 return index;
238 }
239 // Sleep briefly to reduce CPU usage instead of busy-waiting
240 std::this_thread::sleep_for(poll_interval);
241 }
242 }
243
244} // namespace kcenon::thread
A future that can be scheduled on a thread pool.
void wait()
Wait until the result is available.
auto then(F &&continuation) -> pool_future< std::invoke_result_t< F, T > >
Chain another operation after this future completes.
bool valid() const
Check if the future is valid.
std::future_status wait_for(const std::chrono::duration< Rep, Period > &timeout)
Wait for the result with timeout.
bool is_ready() const
Check if the future is ready.
T get()
Wait for the result.
pool_future(std::future< T > &&future)
Construct from a std::future.
void set_exception_at_thread_exit(std::exception_ptr exception)
void set_exception(std::exception_ptr exception)
A promise that can schedule work on a thread pool.
void set_exception_at_thread_exit(std::exception_ptr exception)
Set an exception at thread exit.
pool_future< T > get_future()
Get the associated future.
void set_value(T &&value)
Set the value (move)
pool_promise()=default
Default constructor.
void set_exception(std::exception_ptr exception)
Set an exception.
void set_value(const T &value)
Set the value.
void set_value_at_thread_exit(const T &value)
Set the value at thread exit.
Forward declarations for thread system types.
Error codes and utilities for the thread system.
Core threading foundation of the thread system library.
Definition thread_impl.h:17
void wait_for_all(Futures &... futures)
Wait for all futures to complete.
pool_future< void > make_ready_future()
Create a future that is already ready with void.
size_t wait_for_any(Futures &... futures)
Wait for any future to complete.
pool_future< T > make_exceptional_future(std::exception_ptr exception)
Create a future that is already ready with an exception.
STL namespace.