Thread System 0.3.1
High-performance C++20 thread pool with work stealing and DAG scheduling
Loading...
Searching...
No Matches
sync_primitives.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2024, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
5#pragma once
6
7#include <mutex>
8#include <condition_variable>
9#include <atomic>
10#include <chrono>
11#include <memory>
12
20 template<typename Mutex>
21 class scoped_lock_guard {
22 public:
27 explicit scoped_lock_guard(Mutex& mutex)
28 : mutex_(mutex), locked_(true) {
29 mutex_.lock();
30 }
31
37 template<typename Rep, typename Period>
38 scoped_lock_guard(Mutex& mutex, const std::chrono::duration<Rep, Period>& timeout)
39 : mutex_(mutex), locked_(false) {
40 if constexpr (std::is_same_v<Mutex, std::timed_mutex> ||
41 std::is_same_v<Mutex, std::recursive_timed_mutex>) {
42 locked_ = mutex_.try_lock_for(timeout);
43 } else {
44 // Fallback for mutexes without timeout support
45 locked_ = mutex_.try_lock();
46 }
47 }
48
53 if (locked_) {
54 mutex_.unlock();
55 }
56 }
57
58 // Non-copyable and non-movable
63
68 [[nodiscard]] bool owns_lock() const noexcept {
69 return locked_;
70 }
71
75 void unlock() {
76 if (locked_) {
77 mutex_.unlock();
78 locked_ = false;
79 }
80 }
81
82 private:
83 Mutex& mutex_;
84 bool locked_;
85 };
86
91 public:
94
95 // Non-copyable but movable
100
105 template<typename Lock>
106 void wait(Lock& lock) {
107 cv_.wait(lock);
108 }
109
115 template<typename Lock, typename Predicate>
116 void wait(Lock& lock, Predicate predicate) {
117 cv_.wait(lock, predicate);
118 }
119
126 template<typename Lock, typename Rep, typename Period>
127 bool wait_for(Lock& lock, const std::chrono::duration<Rep, Period>& timeout) {
128 return cv_.wait_for(lock, timeout) == std::cv_status::no_timeout;
129 }
130
138 template<typename Lock, typename Rep, typename Period, typename Predicate>
139 bool wait_for(Lock& lock, const std::chrono::duration<Rep, Period>& timeout, Predicate predicate) {
140 return cv_.wait_for(lock, timeout, predicate);
141 }
142
146 void notify_one() noexcept {
147 cv_.notify_one();
148 }
149
153 void notify_all() noexcept {
154 cv_.notify_all();
155 }
156
157 private:
158 std::condition_variable cv_;
159 };
160
164 class atomic_flag_wrapper {
165 public:
166 atomic_flag_wrapper() noexcept : flag_(ATOMIC_FLAG_INIT) {}
168
169 // Non-copyable but movable
174
180 bool test_and_set(std::memory_order order = std::memory_order_acq_rel) noexcept {
181 return flag_.test_and_set(order);
182 }
183
188 void clear(std::memory_order order = std::memory_order_release) noexcept {
189 flag_.clear(order);
190 }
191
197 bool test(std::memory_order order = std::memory_order_acquire) const noexcept {
198 return flag_.test(order);
199 }
200
205 void wait(bool expected, std::memory_order order = std::memory_order_acquire) const noexcept {
206 flag_.wait(expected, order);
207 }
208
212 void notify_one() noexcept {
213 flag_.notify_one();
214 }
215
219 void notify_all() noexcept {
220 flag_.notify_all();
221 }
222
223 private:
224 std::atomic_flag flag_;
225 };
226
231 public:
234
235 // Non-copyable and non-movable
240
244 void lock() {
245 mutex_.lock();
246 }
247
252 bool try_lock() {
253 return mutex_.try_lock();
254 }
255
259 void unlock() {
260 mutex_.unlock();
261 }
262
266 void lock_shared() {
267 mutex_.lock_shared();
268 }
269
275 return mutex_.try_lock_shared();
276 }
277
282 mutex_.unlock_shared();
283 }
284
285 private:
286 std::shared_mutex mutex_;
287 };
288
289 // Convenience type aliases
290 using unique_lock = std::unique_lock<std::mutex>;
291 using shared_lock = std::shared_lock<shared_mutex_wrapper>;
294}
Enhanced atomic flag with additional operations.
atomic_flag_wrapper & operator=(atomic_flag_wrapper &&)=default
atomic_flag_wrapper(atomic_flag_wrapper &&)=default
void notify_one() noexcept
Notify one thread waiting on this flag.
void wait(bool expected, std::memory_order order=std::memory_order_acquire) const noexcept
Wait until the flag becomes false.
bool test(std::memory_order order=std::memory_order_acquire) const noexcept
Test the flag without modifying it.
void clear(std::memory_order order=std::memory_order_release) noexcept
Clear the flag atomically.
atomic_flag_wrapper(const atomic_flag_wrapper &)=delete
bool test_and_set(std::memory_order order=std::memory_order_acq_rel) noexcept
Test and set the flag atomically.
atomic_flag_wrapper & operator=(const atomic_flag_wrapper &)=delete
void notify_all() noexcept
Notify all threads waiting on this flag.
Enhanced condition variable wrapper with timeout and predicate support.
bool wait_for(Lock &lock, const std::chrono::duration< Rep, Period > &timeout)
Wait with timeout.
condition_variable_wrapper(const condition_variable_wrapper &)=delete
void wait(Lock &lock)
Wait indefinitely for notification.
void notify_one() noexcept
Notify one waiting thread.
void wait(Lock &lock, Predicate predicate)
Wait with predicate until condition is met.
bool wait_for(Lock &lock, const std::chrono::duration< Rep, Period > &timeout, Predicate predicate)
Wait with timeout and predicate.
condition_variable_wrapper(condition_variable_wrapper &&)=default
void notify_all() noexcept
Notify all waiting threads.
condition_variable_wrapper & operator=(const condition_variable_wrapper &)=delete
condition_variable_wrapper & operator=(condition_variable_wrapper &&)=default
RAII-based scoped lock guard with timeout support.
Definition forward.h:205
bool owns_lock() const noexcept
Check if the lock was successfully acquired.
void unlock()
Explicitly release the lock before destruction.
scoped_lock_guard(Mutex &mutex)
Construct and immediately acquire the lock.
scoped_lock_guard(scoped_lock_guard &&)=delete
scoped_lock_guard(const scoped_lock_guard &)=delete
scoped_lock_guard & operator=(const scoped_lock_guard &)=delete
~scoped_lock_guard()
Destructor - automatically releases the lock if held.
scoped_lock_guard(Mutex &mutex, const std::chrono::duration< Rep, Period > &timeout)
Construct and try to acquire the lock with timeout.
scoped_lock_guard & operator=(scoped_lock_guard &&)=delete
Shared mutex wrapper with reader-writer lock semantics.
void lock()
Acquire exclusive (writer) lock.
bool try_lock_shared()
Try to acquire shared (reader) lock.
void unlock()
Release exclusive (writer) lock.
void lock_shared()
Acquire shared (reader) lock.
shared_mutex_wrapper(const shared_mutex_wrapper &)=delete
shared_mutex_wrapper & operator=(shared_mutex_wrapper &&)=delete
shared_mutex_wrapper & operator=(const shared_mutex_wrapper &)=delete
shared_mutex_wrapper(shared_mutex_wrapper &&)=delete
bool try_lock()
Try to acquire exclusive (writer) lock.
void unlock_shared()
Release shared (reader) lock.
std::shared_lock< shared_mutex_wrapper > shared_lock
std::unique_lock< std::mutex > unique_lock