ThreadSchedule 3.0.0
Modern C++ thread management library
Loading...
Searching...
No Matches
inline_pool_backend.hpp
Go to the documentation of this file.
1#pragma once
2
14#include "../../expected.hpp"
15#include "../callable/bind.hpp"
16#include "backend.hpp"
18#include <functional>
19#include <future>
20#include <system_error>
21#include <type_traits>
22#include <vector>
23
25{
26
46{
47public:
48 explicit inline_pool_backend(size_t /*num_threads*/ = 0) {}
49
50 template <typename F, typename... Args>
51 auto
52 submit(F&& f, Args&&... args) -> std::future<bind_result_t<F, Args...>>
53 {
54 auto result = try_submit(std::forward<F>(f), std::forward<Args>(args)...);
55 if (!result.has_value())
56 throw std::runtime_error("inline_pool_backend is shut down");
57 return std::move(result.value());
58 }
59
60 template <typename F, typename... Args>
61 auto
62 try_submit(F&& f, Args&&... args) -> expected<std::future<bind_result_t<F, Args...>>, std::error_code>
63 {
64 using return_type = bind_result_t<F, Args...>;
65 auto bound = bind_args(std::forward<F>(f), std::forward<Args>(args)...);
66 if (stop_)
67 return unexpected(std::make_error_code(std::errc::operation_canceled));
68
69 std::promise<return_type> p;
70 auto future = p.get_future();
71 try
72 {
73 if constexpr (std::is_void_v<return_type>)
74 {
75 bound();
76 p.set_value();
77 }
78 else
79 {
80 p.set_value(bound());
81 }
82 }
83 catch (...)
84 {
85 p.set_exception(std::current_exception());
86 }
87 return future;
88 }
89
90 template <typename F, typename... Args>
91 void
92 post(F&& f, Args&&... args)
93 {
94 auto r = try_post(std::forward<F>(f), std::forward<Args>(args)...);
95 if (!r.has_value())
96 throw std::runtime_error("inline_pool_backend is shut down");
97 }
98
99 template <typename F, typename... Args>
100 auto
102 {
103 auto bound = bind_args(std::forward<F>(f), std::forward<Args>(args)...);
104 if (stop_)
105 return unexpected(std::make_error_code(std::errc::operation_canceled));
106 try
107 {
108 bound();
109 }
110 catch (...)
111 {
112 }
113 return {};
114 }
115
116 template <typename Iterator>
117 auto
118 try_submit_batch(Iterator begin, Iterator end) -> expected<std::vector<std::future<void>>, std::error_code>
119 {
120 if (stop_)
121 return unexpected(std::make_error_code(std::errc::operation_canceled));
122
123 std::vector<std::future<void>> futures;
124 for (auto it = begin; it != end; ++it)
125 {
126 std::promise<void> p;
127 futures.push_back(p.get_future());
128 try
129 {
130 (*it)();
131 p.set_value();
132 }
133 catch (...)
134 {
135 p.set_exception(std::current_exception());
136 }
137 }
138 return futures;
139 }
140
141 template <typename Iterator>
142 auto
143 submit_batch(Iterator begin, Iterator end) -> std::vector<std::future<void>>
144 {
145 auto result = try_submit_batch(begin, end);
146 if (!result.has_value())
147 throw std::runtime_error("inline_pool_backend is shut down");
148 return std::move(result.value());
149 }
150
151 template <typename Iterator, typename F>
152 void
153 parallel_for_each(Iterator begin, Iterator end, F&& func)
154 {
155 static_assert(detail::is_forward_iterator_v<Iterator>, "parallel_for_each requires at least a forward iterator");
156 if (stop_)
157 throw std::system_error(std::make_error_code(std::errc::operation_canceled),
158 "inline_pool_backend::parallel_for_each");
159 for (auto it = begin; it != end; ++it)
160 func(*it);
161 }
162
163 [[nodiscard]] auto
164 size() const noexcept -> size_t
165 {
166 return 0;
167 }
168 [[nodiscard]] auto
169 pending_tasks() const noexcept -> size_t
170 {
171 return 0;
172 }
173
174 void
176 {
177 }
178 void
180 {
181 stop_ = true;
182 }
183
184private:
185 bool stop_{ false };
186};
187
188} // namespace threadschedule::detail
A pool that executes every task inline on the calling thread.
void shutdown(shutdown_policy_backend=shutdown_policy_backend::drain)
void parallel_for_each(Iterator begin, Iterator end, F &&func)
auto try_submit_batch(Iterator begin, Iterator end) -> expected< std::vector< std::future< void > >, std::error_code >
auto submit(F &&f, Args &&... args) -> std::future< bind_result_t< F, Args... > >
auto submit_batch(Iterator begin, Iterator end) -> std::vector< std::future< void > >
auto try_submit(F &&f, Args &&... args) -> expected< std::future< bind_result_t< F, Args... > >, std::error_code >
auto try_post(F &&f, Args &&... args) -> expected< void, std::error_code >
constexpr auto has_value() const noexcept -> bool
Definition expected.hpp:599
Aggregates multiple thread_registry_backend instances into a single queryable view.
std::invoke_result_t< decltype(bind_args(std::declval< F >(), std::declval< Args >()...))& > bind_result_t
Result of invoking the decayed callable and arguments stored by bind_args.
Definition bind.hpp:32
auto bind_args(F &&function, Args &&... args)
Definition bind.hpp:17
Worker identity, CPU selection, and registration helpers.