CommRaT 2.0.0
C++20 Real-Time Messaging Framework
Loading...
Searching...
No Matches
threading.hpp
Go to the documentation of this file.
1
14#pragma once
15
16#include <thread>
17#include <mutex>
18#include <shared_mutex>
19#include <condition_variable>
20#include <atomic>
21#include <functional>
22#include <string>
23#include <cstdint>
24
25// For future realtime support
26#include <pthread.h>
27#include <sched.h>
28
29namespace commrat {
30
34enum class ThreadPriority {
35 IDLE = 0,
36 LOW = 10,
37 NORMAL = 50,
38 HIGH = 75,
39 REALTIME = 99
40};
41
45enum class SchedulingPolicy {
46 NORMAL,
47 FIFO,
50};
51
62
76class Thread {
77public:
81 Thread() = default;
82
89 template<typename Func>
90 Thread(const ThreadConfig& config, Func&& func)
91 : config_(config),
92 thread_([this, f = std::forward<Func>(func)]() mutable {
93 this->thread_function(std::move(f));
94 }) {
95 }
96
100 explicit Thread(const ThreadConfig& config)
101 : config_(config) {
102 }
103
108 if (thread_.joinable()) {
109 thread_.join();
110 }
111 }
112
113 // Non-copyable, movable
114 Thread(const Thread&) = delete;
115 Thread& operator=(const Thread&) = delete;
116 Thread(Thread&&) = default;
117 Thread& operator=(Thread&&) = default;
118
122 template<typename Func>
123 void start(Func&& func) {
124 if (thread_.joinable()) {
125 return; // Already running
126 }
127 thread_ = std::thread([this, f = std::forward<Func>(func)]() mutable {
128 this->thread_function(std::move(f));
129 });
130 }
131
135 void join() {
136 if (thread_.joinable()) {
137 thread_.join();
138 }
139 }
140
144 void detach() {
145 if (thread_.joinable()) {
146 thread_.detach();
147 }
148 }
149
153 bool joinable() const noexcept {
154 return thread_.joinable();
155 }
156
160 std::thread::native_handle_type native_handle() {
161 return thread_.native_handle();
162 }
163
167 std::thread::id get_id() const noexcept {
168 return thread_.get_id();
169 }
170
174 const ThreadConfig& config() const noexcept {
175 return config_;
176 }
177
178private:
182 template<typename Func>
183 void thread_function(Func&& func) {
184 // Set thread name (Linux-specific)
185#ifdef __linux__
186 if (!config_.name.empty()) {
187 pthread_setname_np(pthread_self(), config_.name.c_str());
188 }
189#endif
190
191 // Set priority and scheduling policy
192 apply_thread_config();
193
194 // Run user function
195 func();
196 }
197
201 void apply_thread_config() {
202 pthread_t thread_handle = pthread_self();
203
204 // Set scheduling policy and priority
205 if (config_.policy != SchedulingPolicy::NORMAL ||
206 config_.priority != ThreadPriority::NORMAL) {
207
208 int policy = SCHED_OTHER;
209 switch (config_.policy) {
211 policy = SCHED_FIFO;
212 break;
214 policy = SCHED_RR;
215 break;
216 default:
217 policy = SCHED_OTHER;
218 }
219
220 struct sched_param param;
221 param.sched_priority = static_cast<int>(config_.priority);
222
223 // Note: Requires CAP_SYS_NICE capability or root for SCHED_FIFO/RR
224 pthread_setschedparam(thread_handle, policy, &param);
225 }
226
227 // Set CPU affinity
228 if (config_.cpu_affinity >= 0) {
229 cpu_set_t cpuset;
230 CPU_ZERO(&cpuset);
231 CPU_SET(config_.cpu_affinity, &cpuset);
232 pthread_setaffinity_np(thread_handle, sizeof(cpu_set_t), &cpuset);
233 }
234 }
235
236 ThreadConfig config_;
237 std::thread thread_;
238};
239
245class Mutex {
246public:
247 Mutex() = default;
248 ~Mutex() = default;
249
250 // Non-copyable, non-movable
251 Mutex(const Mutex&) = delete;
252 Mutex& operator=(const Mutex&) = delete;
253
254 void lock() { mutex_.lock(); }
255 bool try_lock() { return mutex_.try_lock(); }
256 void unlock() { mutex_.unlock(); }
257
258 std::mutex& native() { return mutex_; }
259
260private:
261 std::mutex mutex_;
262};
263
271public:
272 SharedMutex() = default;
273 ~SharedMutex() = default;
274
275 // Non-copyable, non-movable
276 SharedMutex(const SharedMutex&) = delete;
278
279 void lock() { mutex_.lock(); } // Exclusive (write) lock
280 void lock_shared() { mutex_.lock_shared(); } // Shared (read) lock
281 bool try_lock() { return mutex_.try_lock(); }
282 bool try_lock_shared() { return mutex_.try_lock_shared(); }
283 void unlock() { mutex_.unlock(); }
284 void unlock_shared() { mutex_.unlock_shared(); }
285
286 std::shared_mutex& native() { return mutex_; }
287
288private:
289 std::shared_mutex mutex_;
290};
291
302using Lock = std::lock_guard<Mutex>;
303using UniqueLock = std::unique_lock<Mutex>;
304
308using SharedLock = std::shared_lock<SharedMutex>;
309
313using UniqueLockShared = std::unique_lock<SharedMutex>;
314
319public:
320 ConditionVariable() = default;
322
323 // Non-copyable, non-movable
326
327 void notify_one() noexcept { cv_.notify_one(); }
328 void notify_all() noexcept { cv_.notify_all(); }
329
330 // Accept std::unique_lock<std::mutex> directly for condition variable compatibility
331 void wait(std::unique_lock<std::mutex>& lock) { cv_.wait(lock); }
332
333 template<typename Predicate>
334 void wait(std::unique_lock<std::mutex>& lock, Predicate pred) {
335 cv_.wait(lock, pred);
336 }
337
338 template<typename Rep, typename Period>
339 std::cv_status wait_for(std::unique_lock<std::mutex>& lock,
340 const std::chrono::duration<Rep, Period>& rel_time) {
341 return cv_.wait_for(lock, rel_time);
342 }
343
344private:
345 std::condition_variable cv_;
346};
347
359#define Synchronized(mutex) \
360 if (commrat::Lock _lock_##__LINE__{mutex}; true)
361
371#define ReadLocked(mutex) \
372 if (commrat::SharedLock _lock_##__LINE__{mutex}; true)
373
383#define WriteLocked(mutex) \
384 if (commrat::UniqueLockShared _lock_##__LINE__{mutex}; true)
385
386} // namespace commrat
Condition variable wrapper.
void notify_all() noexcept
void notify_one() noexcept
ConditionVariable(const ConditionVariable &)=delete
ConditionVariable & operator=(const ConditionVariable &)=delete
void wait(std::unique_lock< std::mutex > &lock)
void wait(std::unique_lock< std::mutex > &lock, Predicate pred)
std::cv_status wait_for(std::unique_lock< std::mutex > &lock, const std::chrono::duration< Rep, Period > &rel_time)
Mutex wrapper (future: realtime mutex support)
Mutex()=default
Mutex & operator=(const Mutex &)=delete
std::mutex & native()
Mutex(const Mutex &)=delete
~Mutex()=default
Shared mutex wrapper (reader-writer lock)
std::shared_mutex & native()
SharedMutex(const SharedMutex &)=delete
SharedMutex & operator=(const SharedMutex &)=delete
Thread wrapper with realtime support.
Definition threading.hpp:76
std::thread::native_handle_type native_handle()
Get native thread handle.
Thread & operator=(const Thread &)=delete
const ThreadConfig & config() const noexcept
Get thread configuration.
Thread(const ThreadConfig &config, Func &&func)
Create and start thread with function.
Definition threading.hpp:90
bool joinable() const noexcept
Check if thread is joinable.
void join()
Join thread (wait for completion)
std::thread::id get_id() const noexcept
Get thread ID.
Thread()=default
Default constructor - no thread running.
void start(Func &&func)
Start thread with function (if not already started)
void detach()
Detach thread.
~Thread()
Destructor - joins if joinable.
Thread(Thread &&)=default
Thread(const ThreadConfig &config)
Create thread without starting (call start() later)
Thread & operator=(Thread &&)=default
Thread(const Thread &)=delete
CommRaT - Modern C++ Real-Time Communication Framework.
std::unique_lock< Mutex > UniqueLock
SchedulingPolicy
Thread scheduling policy.
Definition threading.hpp:45
@ NORMAL
Default OS scheduling (SCHED_OTHER)
@ ROUND_ROBIN
Round-robin realtime (SCHED_RR)
@ FIFO
First-in-first-out realtime (SCHED_FIFO)
@ DEADLINE
Deadline scheduling (SCHED_DEADLINE) - future.
std::shared_lock< SharedMutex > SharedLock
Scoped shared lock (RAII) - for readers.
std::lock_guard< Mutex > Lock
Scoped lock guard (RAII)
std::unique_lock< SharedMutex > UniqueLockShared
Scoped unique lock (RAII) - for writers.
ThreadPriority
Thread priority levels.
Definition threading.hpp:34
@ NORMAL
Normal priority (default)
@ REALTIME
Realtime priority (critical paths)
@ IDLE
Idle priority (background tasks)
@ HIGH
High priority (I/O, event handling)
Thread configuration.
Definition threading.hpp:55
ThreadPriority priority
Definition threading.hpp:57
int cpu_affinity
-1 = no affinity, >= 0 = pin to CPU
Definition threading.hpp:59
SchedulingPolicy policy
Definition threading.hpp:58
size_t stack_size
0 = default, > 0 = custom stack size
Definition threading.hpp:60