ThreadSchedule 2.2.0
Modern C++ thread management library
Loading...
Searching...
No Matches
chaos.hpp
Go to the documentation of this file.
1#pragma once
2
12
13#include "scheduler_policy.hpp"
14#include "thread_registry.hpp"
15#include "thread_wrapper.hpp"
16#include "topology.hpp"
17#include <atomic>
18#include <chrono>
19#include <future>
20#include <random>
21#include <thread>
22
23namespace threadschedule
24{
25
35{
37 std::chrono::milliseconds interval{250};
38
46
48 bool shuffle_affinity{true};
49};
50
87{
88 public:
89 template <typename Predicate>
90 ChaosController(ChaosConfig cfg, Predicate pred) : config_(cfg), stop_(false)
91 {
92 std::promise<Tid> worker_started;
93 auto worker_ready = worker_started.get_future();
94
95 worker_ = ThreadWrapper([this, pred, started = std::move(worker_started)]() mutable {
96 started.set_value(ThreadInfo::get_thread_id());
97 run_loop(pred);
98 });
99
100 worker_tid_ = worker_ready.get();
101 (void)ThreadInfo(worker_tid_).set_name("ts_chaos_ctl");
102 }
103
105 {
106 stop_ = true;
107 if (worker_.joinable())
108 worker_.join();
109 }
110
112 auto operator=(ChaosController const&) -> ChaosController& = delete;
113
114 [[nodiscard]] auto thread_info() const -> std::optional<ThreadInfo>
115 {
116 if (!worker_.joinable() || worker_tid_ == Tid{})
117 return std::nullopt;
118 return ThreadInfo(worker_tid_);
119 }
120
121 auto configure_thread(std::string const& name, SchedulingPolicy policy = SchedulingPolicy::OTHER,
123 {
124 auto info = thread_info();
125 if (!info.has_value())
126 return unexpected(std::make_error_code(std::errc::no_such_process));
127 return detail::configure_thread(info.value(), name, policy, priority);
128 }
129
130 private:
131 template <typename Predicate>
132 void run_loop(Predicate pred)
133 {
134 std::mt19937 rng(std::random_device{}());
135 while (!stop_)
136 {
137 registry().apply(pred, [&](RegisteredThreadInfo const& info) {
138 auto blk = registry().get(info.tid);
139 (void)blk;
140 });
141
142 // Affinity shuffle using topology
143 if (config_.shuffle_affinity)
144 {
145 auto topo = read_topology();
146 size_t idx = 0;
147 registry().apply(pred, [&](RegisteredThreadInfo const& info) {
148 ThreadAffinity aff = affinity_for_node(
149 static_cast<int>(idx % (topo.numa_nodes > 0 ? topo.numa_nodes : 1)), static_cast<int>(idx));
150 (void)registry().set_affinity(info.tid, aff);
151 ++idx;
152 });
153 }
154
155 // Priority jitter around the thread's actual priority
156 if (config_.priority_jitter != 0)
157 {
158 std::uniform_int_distribution<int> dist(-config_.priority_jitter, config_.priority_jitter);
159 registry().apply(pred, [&](RegisteredThreadInfo const& info) {
160 int delta = dist(rng);
161 int baseline = ThreadPriority::normal().value();
162#ifndef _WIN32
163 sched_param sp{};
164 if (sched_getparam(info.tid, &sp) == 0)
165 baseline = sp.sched_priority;
166#endif
167 (void)registry().set_priority(info.tid, ThreadPriority{baseline + delta});
168 });
169 }
170
171 std::this_thread::sleep_for(config_.interval);
172 }
173 }
174
175 ChaosConfig config_;
176 std::atomic<bool> stop_;
177 ThreadWrapper worker_;
178 Tid worker_tid_{};
179};
180
181} // namespace threadschedule
auto configure_thread(std::string const &name, SchedulingPolicy policy=SchedulingPolicy::OTHER, ThreadPriority priority=ThreadPriority::normal()) -> expected< void, std::error_code >
Definition chaos.hpp:121
auto thread_info() const -> std::optional< ThreadInfo >
Definition chaos.hpp:114
ChaosController(ChaosController const &)=delete
ChaosController(ChaosConfig cfg, Predicate pred)
Definition chaos.hpp:90
auto operator=(ChaosController const &) -> ChaosController &=delete
Lightweight handle for querying and controlling a specific OS thread.
static auto get_thread_id() -> Tid
auto set_name(std::string const &name) const -> expected< void, std::error_code >
Value-semantic wrapper for a thread scheduling priority.
static constexpr auto normal() noexcept -> ThreadPriority
Owning wrapper around std::thread with RAII join-on-destroy semantics.
A result type that holds either a value of type T or an error of type E.
Definition expected.hpp:215
Exception thrown by expected::value() when the object is in the error state.
Definition expected.hpp:162
auto configure_thread(ThreadLike &thread, std::string const &name, SchedulingPolicy policy, ThreadPriority priority) -> expected< void, std::error_code >
SchedulingPolicy
Enumeration of available thread scheduling policies.
@ OTHER
Standard round-robin time-sharing.
auto registry() -> ThreadRegistry &
Returns a reference to the process-wide ThreadRegistry.
auto read_topology() -> CpuTopology
Discover basic topology. Linux: reads /sys for NUMA nodes. Windows: single node, sequential CPU indic...
Definition topology.hpp:53
auto affinity_for_node(CpuTopology const &topo, int node_index, int thread_index, int threads_per_node=1) -> ThreadAffinity
Build a ThreadAffinity for the given NUMA node using a pre-read topology.
Definition topology.hpp:150
Scheduling policies, thread priority, and CPU affinity types.
Plain value type holding runtime chaos-testing parameters.
Definition chaos.hpp:35
int priority_jitter
+/- range applied around the current thread priority each interval.
Definition chaos.hpp:45
std::chrono::milliseconds interval
Definition chaos.hpp:37
Process-wide thread registry, control blocks, and composite registry.
Enhanced thread wrappers: ThreadWrapper, JThreadWrapper, and non-owning views.
Hardware topology helpers (CPU count, NUMA nodes) and affinity builders.