ThreadSchedule 3.0.0
Modern C++ thread management library
Loading...
Searching...
No Matches
thread_by_name_view.hpp
Go to the documentation of this file.
1#pragma once
2
8#include "../detail/thread/control.hpp"
9#include "../detail/thread/identity.hpp"
10#include "../detail/try_result.hpp"
11#include "../result.hpp"
12#include "native_thread.hpp"
13
14#include <string>
15#include <string_view>
16#include <system_error>
17#include <utility>
18#include <vector>
19
21{
22
40{
41public:
47 explicit thread_by_name_view(std::string_view name) : identity_(unique_identity_or_throw(name)) {}
48
50 [[nodiscard]] static auto
51 create(std::string_view name) -> result<thread_by_name_view>
52 {
53 return detail::try_result(
55 {
56 auto identity = unique_identity(name);
57 if (!identity)
58 return unexpected(identity.error());
59 return thread_by_name_view(identity_tag{}, identity.value());
60 });
61 }
62
67 [[nodiscard]] static auto
69 {
70 return detail::try_result(
71 [name]() -> result<std::vector<thread_by_name_view>>
72 {
73 auto identities = detail::find_native_threads_by_name(name);
74 if (!identities)
75 return unexpected(identities.error());
76
77 std::vector<thread_by_name_view> views;
78 views.reserve(identities->size());
79 for (auto const& identity : identities.value())
80 views.push_back(thread_by_name_view(identity_tag{}, identity));
81 return views;
82 });
83 }
84
86 [[nodiscard]] auto
87 alive() const noexcept -> bool
88 {
89 return detail::native_thread_is_alive(identity_);
90 }
91
93 [[nodiscard]] auto
94 native_id() const noexcept -> native_thread_id
95 {
96 return identity_.id;
97 }
98
100 auto
102 {
103 return detail::try_result(
104 [this, &config]() -> result<void>
105 {
106 auto const native = detail::to_native(config);
107 auto checked = with_live_identity([](auto /*id*/) -> result<void> { return {}; });
108 if (!checked)
109 return checked;
110 if (native.name)
111 {
112 auto named = set_name(*native.name);
113 if (!named)
114 return named;
115 }
116 if (native.scheduling)
117 {
118 auto scheduled = with_live_identity(
119 [&](auto id) { return detail::apply_scheduling_config(id, id, *native.scheduling); });
120 if (!scheduled)
121 return scheduled;
122 }
123 if (native.affinity)
124 return with_live_identity([&](auto id) { return detail::apply_affinity_checked(id, *native.affinity); });
125 return {};
126 });
127 }
128
130 auto
132 {
133 return with_live_identity(
134 [&](auto id)
135 {
137 detail::native_schedule::posix_nice(static_cast<int>(level)));
138 });
139 }
140
142 auto
144 {
145 return with_live_identity(
146 [&](auto id)
147 { return detail::apply_scheduling_config(id, id, detail::native_schedule::posix_nice(value.value())); });
148 }
149
151 [[nodiscard]] auto
153 {
154 auto value = with_live_identity([&](auto id) { return detail::read_effective_nice(id, id); });
155 return detail::portable_thread_control::get_priority(std::move(value));
156 }
157
159 [[nodiscard]] auto
161 {
162 auto value = with_live_identity([&](auto id) { return detail::read_effective_nice(id, id); });
163 return detail::portable_thread_control::get_nice(std::move(value));
164 }
165
167 auto
168 set_name(std::string const& name) -> result<void>
169 {
170 return with_live_identity([&](auto id) { return detail::apply_name(id, name); });
171 }
172
174 [[nodiscard]] auto
175 get_name() const -> result<std::string>
176 {
177 return with_live_identity([](auto id) { return detail::read_name(id); });
178 }
179
181 auto
183 {
184 return detail::try_result(
185 [this, &affinity]() -> result<void>
186 {
187 auto const native = detail::to_native(affinity);
188 return with_live_identity([&](auto id) { return detail::apply_affinity_checked(id, native); });
189 });
190 }
191
193 [[nodiscard]] auto
195 {
196 auto native = with_live_identity([](auto id) { return detail::read_affinity(id); });
197 return detail::portable_thread_control::get_affinity(std::move(native));
198 }
199
200private:
201 struct identity_tag
202 {
203 };
204
205 thread_by_name_view(identity_tag /*unused*/, detail::native_thread_identity identity) noexcept : identity_(identity)
206 {
207 }
208
209 [[nodiscard]] static auto
210 unique_identity(std::string_view name) -> result<detail::native_thread_identity>
211 {
212 auto identities = detail::find_native_threads_by_name(name);
213 if (!identities)
214 return unexpected(identities.error());
215 if (identities->empty())
216 return unexpected(std::make_error_code(std::errc::no_such_process));
217 if (identities->size() != 1)
218 return unexpected(std::make_error_code(std::errc::invalid_argument));
219 return identities->front();
220 }
221
222 [[nodiscard]] static auto
223 unique_identity_or_throw(std::string_view name) -> detail::native_thread_identity
224 {
225 auto identity = unique_identity(name);
226 if (!identity)
227 throw std::system_error(identity.error(), "thread_by_name_view");
228 return identity.value();
229 }
230
231 template <typename Function>
232 [[nodiscard]] auto
233 with_live_identity(Function&& function) const
234 -> decltype(std::declval<Function>()(std::declval<detail::native_thread_id>()))
235 {
236 using result_type = decltype(std::declval<Function>()(std::declval<detail::native_thread_id>()));
237 auto const inactive = [] { return result_type(unexpected(std::make_error_code(std::errc::no_such_process))); };
238 if (!alive())
239 return inactive();
240
241 auto result_value = std::forward<Function>(function)(identity_.id);
242 if (result_value && !alive())
243 return inactive();
244 return result_value;
245 }
246
247 detail::native_thread_identity identity_;
248};
249
250} // namespace threadschedule::advanced
Non-owning control view found by an exact process-thread name.
auto configure(thread_config const &config) -> result< void >
Apply a portable thread configuration to the target.
auto alive() const noexcept -> bool
Return whether the original native thread identity is still live.
auto set_nice(nice_value value) -> result< void >
Set an explicit nice value on the target.
static auto find_all(std::string_view name) -> result< std::vector< thread_by_name_view > >
Return every exact name match ordered by native thread ID.
static auto create(std::string_view name) -> result< thread_by_name_view >
Find exactly one named process thread without throwing.
thread_by_name_view(std::string_view name)
Find exactly one process thread with name.
auto set_priority(priority_level level) -> result< void >
Set a portable priority preset on the target.
auto set_affinity(thread_affinity const &affinity) -> result< void >
Set target CPU affinity with exact readback and rollback.
auto get_priority() const -> result< priority_level >
Query the effective portable priority preset.
auto get_affinity() const -> result< thread_affinity >
Query target CPU affinity.
auto get_name() const -> result< std::string >
Query the current OS-visible target name.
auto native_id() const noexcept -> native_thread_id
Return the platform-native process thread ID.
auto get_nice() const -> result< nice_value >
Query the effective nice value.
auto set_name(std::string const &name) -> result< void >
Set the OS-visible target name without changing view identity.
Strongly-typed nice value in the POSIX range $[-20, 19]$.
Portable thread configuration bundle.
constexpr auto posix_nice(int nice_value) noexcept -> native_scheduling_config
Definition native.hpp:313
auto read_effective_nice(NativeHandle handle, native_thread_id tid) -> expected< int, std::error_code >
Definition native.hpp:847
auto apply_affinity_checked(NativeHandle handle, native_thread_affinity const &affinity) -> expected< void, std::error_code >
Definition native.hpp:790
constexpr auto to_native(shutdown_policy policy) noexcept -> shutdown_policy_backend
Definition shutdown.hpp:10
auto native_thread_is_alive(native_thread_identity const &identity) noexcept -> bool
Definition identity.hpp:74
auto apply_scheduling_config(NativeHandle handle, native_thread_id tid, native_scheduling_config const &config) -> expected< void, std::error_code >
Definition native.hpp:814
auto try_result(Function &&function) -> decltype(std::forward< Function >(function)())
auto find_native_threads_by_name(std::string_view name) -> result< std::vector< native_thread_identity > >
Definition identity.hpp:89
priority_level
Portable non-realtime priority levels.
Native thread identity and handle escape hatches.