roo_threads
API Documentation for roo_threads
Loading...
Searching...
No Matches
mutex.h
Go to the documentation of this file.
1#pragma once
2
4#include "roo_time.h"
5
6#ifdef ROO_THREADS_SINGLETHREADED
7
8#include "roo_backport.h"
9#include "roo_backport/move.h"
10
11namespace roo_threads {
12/// @brief Backend namespace for single-threaded synchronization fallbacks.
13namespace singlethreaded {
14
15/// @ingroup roo_threads_api_mutex
16/// @brief Single-threaded backend implementation of `roo::mutex`.
17/// @copydoc roo_threads::doc::mutex
18class mutex {
19 public:
20 /// @copydoc roo_threads::doc::mutex::mutex
21 mutex() noexcept = default;
22 ~mutex() = default;
23
24 mutex(const mutex&) = delete;
25 mutex& operator=(const mutex&) = delete;
26
27 /// @copydoc roo_threads::doc::mutex::lock
28 void lock() {}
29 /// @copydoc roo_threads::doc::mutex::try_lock
30 bool try_lock() { return true; }
31
32 /// @copydoc roo_threads::doc::mutex::unlock
33 void unlock() {}
34};
35
36template <typename Mutex>
37/// @ingroup roo_threads_api_mutex
38class lock_guard {
39 public:
40 typedef Mutex mutex_type;
41
42 /// @copydoc roo_threads::doc::lock_guard::lock_guard
43 explicit lock_guard(mutex_type& mutex) {}
44
45 lock_guard(const lock_guard&) = delete;
46 lock_guard& operator=(const lock_guard&) = delete;
47};
48
49// Do not lock the associated mutex.
50/// @ingroup roo_threads_api_mutex
51/// @copydoc roo_threads::doc::defer_lock_t
52struct defer_lock_t {
53 explicit defer_lock_t() = default;
54};
55
56// Try to lock the associated mutex without blocking.
57/// @ingroup roo_threads_api_mutex
58/// @copydoc roo_threads::doc::try_to_lock_t
59struct try_to_lock_t {
60 explicit try_to_lock_t() = default;
61};
62
63// Assume the calling thread already holds a non-shared lock (i.e., a lock
64// acquired by lock, try_lock, try_lock_for, or try_lock_until) on the mutex.
65/// @ingroup roo_threads_api_mutex
66/// @copydoc roo_threads::doc::adopt_lock_t
67struct adopt_lock_t {
68 explicit adopt_lock_t() = default;
69};
70
71#if __cplusplus > 201402L
72inline constexpr defer_lock_t defer_lock{};
73inline constexpr try_to_lock_t try_to_lock{};
74inline constexpr adopt_lock_t adopt_lock{};
75#else
76constexpr defer_lock_t defer_lock{};
77constexpr try_to_lock_t try_to_lock{};
78constexpr adopt_lock_t adopt_lock{};
79#endif
80
81template <typename Mutex>
82/// @ingroup roo_threads_api_mutex
83class unique_lock {
84 public:
85 typedef Mutex mutex_type;
86
87 /// @copydoc roo_threads::doc::unique_lock::unique_lock() noexcept
88 unique_lock() noexcept : lock_(nullptr), owns_(false) {}
89
90 /// @copydoc roo_threads::doc::unique_lock::unique_lock(mutex_type&)
91 explicit unique_lock(mutex_type& mutex) : lock_(&mutex), owns_(false) {
92 lock();
93 }
94
95 /// @copydoc
96 /// roo_threads::doc::unique_lock::unique_lock(mutex_type&,defer_lock_t)
97 unique_lock(mutex_type& mutex, defer_lock_t) noexcept
98 : lock_(&mutex), owns_(false) {}
99
100 /// @copydoc
101 /// roo_threads::doc::unique_lock::unique_lock(mutex_type&,try_to_lock_t)
102 unique_lock(mutex_type& mutex, try_to_lock_t)
103 : lock_(&mutex), owns_(lock_->try_lock()) {}
104
105 /// @copydoc
106 /// roo_threads::doc::unique_lock::unique_lock(mutex_type&,adopt_lock_t)
107 unique_lock(mutex_type& mutex, adopt_lock_t) noexcept
108 : lock_(&mutex), owns_(true) {}
109
110 /// @copydoc
111 /// roo_threads::doc::unique_lock::unique_lock(mutex_type&,roo_time::Uptime)
112 unique_lock(mutex_type& mutex, const roo_time::Uptime& tp)
113 : lock_(&mutex), owns_(lock_->try_lock_until(tp)) {}
114
115 /// @copydoc
116 /// roo_threads::doc::unique_lock::unique_lock(mutex_type&,roo_time::Duration)
117 unique_lock(mutex_type& mutex, const roo_time::Duration& duration)
118 : lock_(&mutex), owns_(lock_->try_lock_for(duration)) {}
119
120 /// @copydoc roo_threads::doc::unique_lock::~unique_lock
121 ~unique_lock() {
122 if (owns_) unlock();
123 }
124
125 unique_lock(const unique_lock&) = delete;
126 unique_lock& operator=(const unique_lock&) = delete;
127
128 /// @copydoc roo_threads::doc::unique_lock::unique_lock(unique_lock&&)
129 unique_lock(unique_lock&& lock) noexcept
130 : lock_(lock.lock_), owns_(lock.owns_) {
131 lock.lock_ = 0;
132 lock.owns_ = false;
133 }
134
135 /// @copydoc roo_threads::doc::unique_lock::operator=(unique_lock&&)
136 unique_lock& operator=(unique_lock&& lock) noexcept {
137 if (owns_) unlock();
138
139 unique_lock(roo::move(lock)).swap(*this);
140
141 lock.lock_ = 0;
142 lock.owns_ = false;
143
144 return *this;
145 }
146
147 /// @copydoc roo_threads::doc::unique_lock::lock
148 void lock() {
149 lock_->lock();
150 owns_ = true;
151 }
152
153 /// @copydoc roo_threads::doc::unique_lock::try_lock
154 bool try_lock() {
155 owns_ = lock_->try_lock();
156 return owns_;
157 }
158
159 /// @copydoc roo_threads::doc::unique_lock::try_lock_until
160 bool try_lock_until(const roo_time::Uptime& tp) {
161 owns_ = lock_->try_lock_until(tp);
162 return owns_;
163 }
164
165 /// @copydoc roo_threads::doc::unique_lock::try_lock_for
166 bool try_lock_for(const roo_time::Duration& duration) {
167 owns_ = lock_->try_lock_for(duration);
168 return owns_;
169 }
170
171 /// @copydoc roo_threads::doc::unique_lock::unlock
172 void unlock() {
173 if (lock_ != nullptr) {
174 lock_->unlock();
175 owns_ = false;
176 }
177 }
178
179 /// @copydoc roo_threads::doc::unique_lock::swap
180 void swap(unique_lock& other) noexcept {
181 std::swap(lock_, other.lock_);
182 std::swap(owns_, other.owns_);
183 }
184
185 /// @copydoc roo_threads::doc::unique_lock::release
186 mutex_type* release() noexcept {
187 mutex_type* ret = lock_;
188 lock_ = nullptr;
189 owns_ = false;
190 return ret;
191 }
192
193 /// @copydoc roo_threads::doc::unique_lock::owns_lock
194 bool owns_lock() const noexcept { return owns_; }
195
196 /// @copydoc roo_threads::doc::unique_lock::operator bool
197 explicit operator bool() const noexcept { return owns_lock(); }
198
199 /// @copydoc roo_threads::doc::unique_lock::mutex
200 mutex_type* mutex() const noexcept { return lock_; }
201
202 private:
203 mutex_type* lock_;
204 bool owns_;
205};
206
207} // namespace singlethreaded
208} // namespace roo_threads
209
210#endif // ROO_THREADS_USE_CPPSTD