ThreadSchedule 3.0.0
Modern C++ thread management library
Loading...
Searching...
No Matches
thread.hpp
Go to the documentation of this file.
1#pragma once
2
12#include "thread_config.hpp"
13
14#include <cstdint>
15#include <memory>
16#include <string>
17#include <thread>
18#include <type_traits>
19#include <utility>
20
21namespace threadschedule
22{
23class thread_view;
24
28class thread
29{
30public:
32 thread() = default;
39 explicit thread(std::thread&& value) noexcept : impl_(std::move(value)) {}
45 template <typename F, typename... Args,
46 std::enable_if_t<
47 !std::is_same_v<std::decay_t<F>, thread> && !std::is_same_v<std::decay_t<F>, thread_config>, int> = 0>
48 explicit thread(F&& function, Args&&... args) : impl_(std::forward<F>(function), std::forward<Args>(args)...)
49 {
50 }
51
58 template <typename F, typename... Args>
59 thread(thread_config const& config, F&& function, Args&&... args)
60 : impl_(make_configured_impl(config, std::forward<F>(function), std::forward<Args>(args)...))
61 {
62 }
63
64 thread(thread&&) noexcept = default;
65 auto operator=(thread&&) noexcept -> thread& = default;
66 thread(thread const&) = delete;
67 auto operator=(thread const&) -> thread& = delete;
68
74 template <typename F, typename... Args>
75 static auto
76 create(F&& function, Args&&... args)
77 -> std::enable_if_t<!std::is_same_v<std::decay_t<F>, thread_config>, result<thread>>
78 {
80 { return thread(std::forward<F>(function), std::forward<Args>(args)...); });
81 }
82
89 template <typename F, typename... Args>
90 static auto
91 create(thread_config const& config, F&& function, Args&&... args) -> result<thread>
92 {
94 { return thread(config, std::forward<F>(function), std::forward<Args>(args)...); });
95 }
96
98 auto
100 {
101 return detail::thread_lifecycle::join(impl_);
102 }
103
105 void
107 {
108 detail::thread_lifecycle::join_or_throw(impl_, "thread::join");
109 }
110
112 auto
114 {
115 return detail::thread_lifecycle::detach(impl_);
116 }
117
119 void
121 {
122 detail::thread_lifecycle::detach_or_throw(impl_, "thread::detach");
123 }
124
126 [[nodiscard]] auto
127 joinable() const noexcept -> bool
128 {
129 return impl_.joinable();
130 }
131
133 [[nodiscard]] auto
134 get_id() const noexcept -> std::thread::id
135 {
136 return impl_.get_id();
137 }
138
140 [[nodiscard]] static auto
141 hardware_concurrency() noexcept -> unsigned
142 {
143 return std::thread::hardware_concurrency();
144 }
145
147 auto
149 {
150 return detail::portable_thread_control::configure(impl_, config);
151 }
152
154 auto
156 {
157 return detail::portable_thread_control::set_priority(impl_, level);
158 }
159
161 auto
163 {
164 return detail::portable_thread_control::set_nice(impl_, value);
165 }
166
168 [[nodiscard]] auto
170 {
171 return detail::portable_thread_control::get_priority(impl_.get_nice_value());
172 }
173
175 [[nodiscard]] auto
177 {
178 return detail::portable_thread_control::get_nice(impl_.get_nice_value());
179 }
180
182 auto
183 set_name(std::string const& name) -> result<void>
184 {
185 return impl_.set_name(name);
186 }
187
189 [[nodiscard]] auto
190 get_name() const -> result<std::string>
191 {
192 return impl_.get_name();
193 }
194
196 auto
198 {
199 return detail::portable_thread_control::set_affinity(impl_, affinity);
200 }
201
203 [[nodiscard]] auto
205 {
206 return detail::portable_thread_control::get_affinity(impl_.get_affinity());
207 }
208
210 [[nodiscard]] auto
211 release() noexcept -> std::thread
212 {
213 return impl_.release();
214 }
215
216private:
218 friend class thread_view;
219
220 template <typename F, typename... Args>
221 static auto
222 make_configured_impl(thread_config const& config, F&& function, Args&&... args) -> detail::thread_backend
223 {
224 auto gate = std::make_shared<detail::thread_start_gate>();
226 [gate, callable = detail::bind_args(std::forward<F>(function), std::forward<Args>(args)...)]() mutable
227 {
228 if (gate->wait())
229 callable();
230 });
231
232 auto rollback = detail::make_scope_exit(
233 [&]() noexcept
234 {
235 gate->release(false);
236 try
237 {
238 if (value.joinable())
239 value.join();
240 }
241 catch (...)
242 {
243 }
244 });
245 auto configured = value.configure(detail::to_native(config));
246 if (!configured)
247 {
248 throw std::system_error(configured.error(), "thread configuration");
249 }
250 gate->release(true);
251 rollback.release();
252 return value;
253 }
254
255 detail::thread_backend impl_;
256};
257
258} // namespace threadschedule
C++17 callable and argument binding with move-only support.
auto set_name(std::string const &name) -> expected< void, std::error_code >
auto get_affinity() const -> expected< native_thread_affinity, std::error_code >
auto get_nice_value() const -> expected< int, std::error_code >
auto configure(native_scheduling_config const &config) -> expected< void, std::error_code >
auto get_name() const -> expected< std::string, std::error_code >
Owning wrapper around std::thread with RAII join-on-destroy semantics.
auto release() noexcept -> std::thread
Strongly-typed nice value in the POSIX range $[-20, 19]$.
Portable thread configuration bundle.
Non-owning view over a running thread or jthread.
Owning thread wrapper with result-based lifecycle/configuration API.
Definition thread.hpp:29
auto detach() -> result< void >
Detach the thread.
Definition thread.hpp:113
auto release() noexcept -> std::thread
Release ownership and return underlying std::thread.
Definition thread.hpp:211
static auto create(thread_config const &config, F &&function, Args &&... args) -> result< thread >
Create configured thread without throwing.
Definition thread.hpp:91
static auto create(F &&function, Args &&... args) -> std::enable_if_t<!std::is_same_v< std::decay_t< F >, thread_config >, result< thread > >
Create thread without throwing.
Definition thread.hpp:76
thread(std::thread &&value) noexcept
Take ownership of an existing std::thread.
Definition thread.hpp:39
auto set_name(std::string const &name) -> result< void >
Set thread name.
Definition thread.hpp:183
thread(thread_config const &config, F &&function, Args &&... args)
Start a thread and apply thread_config before user code runs.
Definition thread.hpp:59
auto set_nice(nice_value value) -> result< void >
Set explicit nice value.
Definition thread.hpp:162
static auto hardware_concurrency() noexcept -> unsigned
Forward std::thread::hardware_concurrency().
Definition thread.hpp:141
auto get_nice() const -> result< nice_value >
Query current nice value.
Definition thread.hpp:176
void detach_or_throw()
Throwing counterpart to detach.
Definition thread.hpp:120
thread(thread &&) noexcept=default
thread(F &&function, Args &&... args)
Start a thread from callable and arguments.
Definition thread.hpp:48
auto set_priority(priority_level level) -> result< void >
Set portable priority preset.
Definition thread.hpp:155
thread()=default
Construct an empty, non-joinable thread object.
void join_or_throw()
Throwing counterpart to join.
Definition thread.hpp:106
auto configure(thread_config const &config) -> result< void >
Apply a full portable thread configuration to the running thread.
Definition thread.hpp:148
auto get_priority() const -> result< priority_level >
Query current portable priority preset.
Definition thread.hpp:169
auto get_name() const -> result< std::string >
Query thread name if supported by platform/backend.
Definition thread.hpp:190
auto get_id() const noexcept -> std::thread::id
Return std::thread id of the owned thread.
Definition thread.hpp:134
auto join() -> result< void >
Join the thread.
Definition thread.hpp:99
auto set_affinity(thread_affinity const &affinity) -> result< void >
Apply CPU affinity set.
Definition thread.hpp:197
auto get_affinity() const -> result< thread_affinity >
Query current CPU affinity.
Definition thread.hpp:204
auto joinable() const noexcept -> bool
Return whether the thread object owns a running thread.
Definition thread.hpp:127
auto make_scope_exit(F &&function) -> scope_exit< std::decay_t< F > >
constexpr auto to_native(shutdown_policy policy) noexcept -> shutdown_policy_backend
Definition shutdown.hpp:10
auto bind_args(F &&function, Args &&... args)
Definition bind.hpp:17
auto try_result(Function &&function) -> decltype(std::forward< Function >(function)())
priority_level
Portable non-realtime priority levels.
C++17 thread wrappers and non-owning views.
Portable thread startup and runtime configuration.