ThreadSchedule 2.0.0
Modern C++ thread management library
Loading...
Searching...
No Matches
futures.hpp
Go to the documentation of this file.
1#pragma once
2
11
12#include "expected.hpp"
13
14#include <chrono>
15#include <exception>
16#include <future>
17#include <utility>
18#include <vector>
19
20namespace threadschedule
21{
22
33template <typename T>
34auto when_all(std::vector<std::future<T>>& futures) -> std::vector<T>
35{
36 std::vector<T> results;
37 results.reserve(futures.size());
38 std::exception_ptr first_error;
39
40 for (auto& f : futures)
41 {
42 try
43 {
44 results.push_back(f.get());
45 }
46 catch (...)
47 {
48 if (!first_error)
49 first_error = std::current_exception();
50 results.emplace_back();
51 }
52 }
53
54 if (first_error)
55 std::rethrow_exception(first_error);
56
57 return results;
58}
59
65inline void when_all(std::vector<std::future<void>>& futures)
66{
67 std::exception_ptr first_error;
68
69 for (auto& f : futures)
70 {
71 try
72 {
73 f.get();
74 }
75 catch (...)
76 {
77 if (!first_error)
78 first_error = std::current_exception();
79 }
80 }
81
82 if (first_error)
83 std::rethrow_exception(first_error);
84}
85
94template <typename T>
95auto when_all_settled(std::vector<std::future<T>>& futures)
96 -> std::vector<expected<T, std::exception_ptr>>
97{
98 std::vector<expected<T, std::exception_ptr>> results;
99 results.reserve(futures.size());
100
101 for (auto& f : futures)
102 {
103 try
104 {
105 results.push_back(f.get());
106 }
107 catch (...)
108 {
109 results.push_back(unexpected(std::current_exception()));
110 }
111 }
112
113 return results;
114}
115
119inline auto when_all_settled(std::vector<std::future<void>>& futures)
120 -> std::vector<expected<void, std::exception_ptr>>
121{
122 std::vector<expected<void, std::exception_ptr>> results;
123 results.reserve(futures.size());
124
125 for (auto& f : futures)
126 {
127 try
128 {
129 f.get();
130 results.emplace_back();
131 }
132 catch (...)
133 {
134 results.push_back(unexpected(std::current_exception()));
135 }
136 }
137
138 return results;
139}
140
153template <typename T>
154auto when_any(std::vector<std::future<T>>& futures) -> std::pair<size_t, T>
155{
156 while (true)
157 {
158 for (size_t i = 0; i < futures.size(); ++i)
159 {
160 if (futures[i].wait_for(std::chrono::milliseconds(1)) == std::future_status::ready)
161 return {i, futures[i].get()};
162 }
163 }
164}
165
171inline auto when_any(std::vector<std::future<void>>& futures) -> size_t
172{
173 while (true)
174 {
175 for (size_t i = 0; i < futures.size(); ++i)
176 {
177 if (futures[i].wait_for(std::chrono::milliseconds(1)) == std::future_status::ready)
178 {
179 futures[i].get();
180 return i;
181 }
182 }
183 }
184}
185
186} // namespace threadschedule
Exception thrown by expected::value() when the object is in the error state.
Definition expected.hpp:162
Polyfill for std::expected (C++23) for pre-C++23 compilers.
auto when_all(std::vector< std::future< T > > &futures) -> std::vector< T >
Block until all futures complete, returning results in submission order.
Definition futures.hpp:34
auto when_all_settled(std::vector< std::future< T > > &futures) -> std::vector< expected< T, std::exception_ptr > >
Block until all futures complete, returning an expected per slot.
Definition futures.hpp:95
auto when_any(std::vector< std::future< T > > &futures) -> std::pair< size_t, T >
Block until the first future becomes ready.
Definition futures.hpp:154