23#if defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L
33 jthread() noexcept = default;
40 explicit jthread(
std::jthread&& value) noexcept : impl_(
std::move(value)) {}
47 typename F,
typename... Args,
48 std::enable_if_t<!std::is_same_v<std::decay_t<F>, jthread> && !std::is_same_v<std::decay_t<F>, thread_config>
49 && std::is_constructible_v<std::jthread, F, Args...>,
51 explicit jthread(F&& function, Args&&... args)
52 : impl_(make_impl(native_id_,
std::forward<F>(function),
std::forward<Args>(args)...))
62 template <
typename F,
typename... Args>
63 jthread(thread_config
const& config, F&& function, Args&&... args)
64 : impl_(make_configured_impl(config, native_id_,
std::forward<F>(function),
std::forward<Args>(args)...))
68 jthread(jthread&&) noexcept = default;
69 auto operator=(jthread&&) noexcept -> jthread& = default;
70 jthread(jthread const&) = delete;
71 auto operator=(jthread const&) -> jthread& = delete;
78 template <typename F, typename... Args>
80 create(F&& function, Args&&... args)
81 ->
std::enable_if_t<!
std::is_same_v<
std::decay_t<F>, thread_config>, result<jthread>>
83 return detail::try_result([&]() -> result<jthread>
84 {
return jthread(std::forward<F>(function), std::forward<Args>(args)...); });
93 template <
typename F,
typename... Args>
95 create(thread_config
const& config, F&& function, Args&&... args) -> result<jthread>
97 return detail::try_result([&]() -> result<jthread>
98 {
return jthread(config, std::forward<F>(function), std::forward<Args>(args)...); });
103 join() -> result<void>
105 return detail::thread_lifecycle::join(impl_);
112 detail::thread_lifecycle::join_or_throw(impl_,
"jthread::join");
117 detach() -> result<void>
119 return detail::thread_lifecycle::detach(impl_);
126 detail::thread_lifecycle::detach_or_throw(impl_,
"jthread::detach");
131 joinable() const noexcept ->
bool
133 return impl_.joinable();
138 get_id() const noexcept ->
std::jthread::
id
140 return impl_.get_id();
144 [[nodiscard]]
static auto
145 hardware_concurrency() noexcept ->
unsigned
147 return std::thread::hardware_concurrency();
152 request_stop() noexcept ->
bool
154 return impl_.request_stop();
159 stop_requested() const noexcept ->
bool
161 return impl_.get_stop_token().stop_requested();
166 get_stop_token() const noexcept ->
std::stop_token
168 return impl_.get_stop_token();
173 get_stop_source() noexcept ->
std::stop_source
175 return impl_.get_stop_source();
180 configure(thread_config
const& config) -> result<void>
182 auto view = native_view();
183 return detail::portable_thread_control::configure(view, config);
188 set_priority(priority_level level) -> result<void>
190 auto view = native_view();
191 return detail::portable_thread_control::set_priority(view, level);
196 set_nice(nice_value value) -> result<void>
198 auto view = native_view();
199 return detail::portable_thread_control::set_nice(view, value);
204 get_priority() const -> result<priority_level>
206 auto view = native_view();
207 return detail::portable_thread_control::get_priority(view.get_nice_value());
212 get_nice() const -> result<nice_value>
214 auto view = native_view();
215 return detail::portable_thread_control::get_nice(view.get_nice_value());
220 set_name(std::string
const& name) -> result<void>
222 auto view = native_view();
223 return view.set_name(name);
230 auto view = native_view();
231 return view.get_name();
236 set_affinity(thread_affinity
const& affinity) -> result<void>
238 auto view = native_view();
239 return detail::portable_thread_control::set_affinity(view, affinity);
244 get_affinity() const -> result<thread_affinity>
246 auto view = native_view();
247 return detail::portable_thread_control::get_affinity(view.get_affinity());
252 release() noexcept ->
std::jthread
254 auto value = std::move(impl_);
260 friend struct detail::native_thread_access;
261 friend class thread_view;
263 using native_view_type = detail::basic_thread_backend<std::jthread, detail::non_owning_tag>;
266 native_view() const -> native_view_type
268 return native_view_type(
const_cast<std::jthread&
>(impl_), native_id_);
271 template <
typename F,
typename... Args>
273 make_impl(detail::native_thread_id& native_id, F&& function, Args&&... args) -> std::jthread
275 using function_type = std::decay_t<F>;
276 auto identity = std::make_shared<detail::thread_identity_state>();
278 [identity, callable = function_type(std::forward<F>(function)),
279 arguments = std::make_tuple(std::forward<Args>(args)...)](std::stop_token token)
mutable
281 identity->publish(detail::current_native_thread_id());
282 detail::invoke_jthread_callable(callable, std::move(arguments), std::move(token));
288 template <
typename F,
typename... Args>
290 make_configured_impl(thread_config
const& config, detail::native_thread_id& native_id, F&& function, Args&&... args)
293 using function_type = std::decay_t<F>;
294 auto gate = std::make_shared<detail::thread_start_gate>();
295 auto identity = std::make_shared<detail::thread_identity_state>();
297 [gate, identity, callable = function_type(std::forward<F>(function)),
298 arguments = std::make_tuple(std::forward<Args>(args)...)](std::stop_token token)
mutable
300 identity->publish(detail::current_native_thread_id());
303 detail::invoke_jthread_callable(callable, std::move(arguments), std::move(token));
307 auto rollback = detail::make_scope_exit([&]()
noexcept { gate->release(
false); });
308 native_view_type view(value, native_id);
309 auto configured = view.configure(detail::to_native(config));
312 throw std::system_error(configured.error(),
"jthread configuration");
319 detail::native_thread_id native_id_{};
auto native_id(thread_id id) noexcept -> result< native_thread_id >
auto set_name(std::string const &name) -> result< void >
Set the calling thread name.
auto get_name() -> result< std::string >
Query the calling thread name.
C++17 thread wrappers and non-owning views.
Portable thread startup and runtime configuration.