µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
mutex
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ distribution.
3 * (https://github.com/micro-os-plus)
4 * Copyright (c) 2016 Liviu Ionescu.
5 *
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense, and/or
11 * sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following
13 * conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28/*
29 * The code is inspired by LLVM libcxx and GNU libstdc++-v3.
30 */
31
32#ifndef CMSIS_PLUS_ESTD_MUTEX_
33#define CMSIS_PLUS_ESTD_MUTEX_
34
35// ----------------------------------------------------------------------------
36
37// Include the next <mutex> file found in the search path.
38#pragma GCC diagnostic push
39#if defined(__clang__)
40#pragma clang diagnostic ignored "-Wgnu-include-next"
41#endif
42#include_next <mutex>
43#pragma GCC diagnostic pop
44
45#include <tuple>
46#include <cerrno>
47
48#include <cmsis-plus/rtos/os.h>
49
52
53// ----------------------------------------------------------------------------
54
55#pragma GCC diagnostic push
56
57#if defined(__clang__)
58#pragma clang diagnostic ignored "-Wc++98-compat"
59#endif
60
61// ----------------------------------------------------------------------------
62
63namespace os
64{
65 namespace estd
66 {
67 // ------------------------------------------------------------------------
68
74 // ========================================================================
75 class mutex
76 {
77 private:
78
80
81 public:
82
84
85 /* constexpr in ISO */
86 mutex () noexcept;
87
88 ~mutex () = default;
89
90 mutex (const mutex&) = delete;
91 mutex&
92 operator= (const mutex&) = delete;
93
94 void
95 lock ();
96
97 bool
98 try_lock ();
99
100 void
101 unlock ();
102
104 native_handle ();
105
106 protected:
107
109 };
110
111 // ========================================================================
112
114 {
115 private:
116
118
119 public:
120
122
124
125 ~recursive_mutex () = default;
126
129 operator= (const recursive_mutex&) = delete;
130
131 void
132 lock ();
133
134 bool
135 try_lock () noexcept;
136
137 void
138 unlock ();
139
141 native_handle ();
142
143 protected:
144
146 };
147
148 // ========================================================================
149
150 class timed_mutex : public mutex
151 {
152 public:
153
154 timed_mutex () = default;
155
156 ~timed_mutex () = default;
157
158 timed_mutex (const timed_mutex&) = delete;
160 operator= (const timed_mutex&) = delete;
161
162 template<typename Rep_T, typename Period_T>
163 bool
164 try_lock_for (const std::chrono::duration<Rep_T, Period_T>& rel_time);
165
166 template<typename Clock_T, typename Duration_T>
167 bool
168 try_lock_until (
169 const std::chrono::time_point<Clock_T, Duration_T>& abs_time);
170 };
171
172 // ========================================================================
173
175 {
176 public:
177
179
181
184 operator= (const recursive_timed_mutex&) = delete;
185
186 template<typename Rep_T, typename Period_T>
187 bool
188 try_lock_for (const std::chrono::duration<Rep_T, Period_T>& rel_time);
189
190 template<typename Clock_T, typename Duration_T>
191 bool
192 try_lock_until (
193 const std::chrono::time_point<Clock_T, Duration_T>& abs_time);
194 };
195
200 // ========================================================================
201 // Inline & template implementations.
202 // ========================================================================
203 inline
204 mutex::mutex () noexcept
205 {
206 ;
207 }
208
211 {
212 return &nm_;
213 }
214
215 // ========================================================================
216
217 inline
219 nm_
221 {
222 ;
223 }
224
227 {
228 return &nm_;
229 }
230
231 // ========================================================================
232
233#pragma GCC diagnostic push
234#pragma GCC diagnostic ignored "-Waggregate-return"
235
236 template<typename Rep_T, typename Period_T>
237 bool
239 const std::chrono::duration<Rep_T, Period_T>& rel_time)
240 {
241 using namespace std::chrono;
243 if (rel_time > duration<Rep_T, Period_T>::zero ())
244 {
245 ticks =
247 os::estd::chrono::systicks> (rel_time).count ());
248 }
249
251 res = nm_.timed_lock (ticks);
252 if (res == os::rtos::result::ok)
253 {
254 return true;
255 }
256 else if (res == ETIMEDOUT)
257 {
258 return false;
259 }
260
261 os::estd::__throw_system_error (static_cast<int> (res),
262 "timed_mutex try_lock failed");
263 return false;
264 }
265
266 template<typename Clock_T, typename Duration_T>
267 bool
269 const std::chrono::time_point<Clock_T, Duration_T>& abs_time)
270 {
271 using clock = Clock_T;
272
273 auto now = clock::now ();
274 while (now < abs_time)
275 {
276 if (try_lock_for (abs_time - now))
277 {
278 return true;
279 }
280 now = clock::now ();
281 }
282
283 return false;
284 }
285
286#pragma GCC diagnostic pop
287
288 // ========================================================================
289
290 template<typename Rep_T, typename Period_T>
291 bool
293 const std::chrono::duration<Rep_T, Period_T>& rel_time)
294 {
295 using namespace std::chrono;
297 if (rel_time > duration<Rep_T, Period_T>::zero ())
298 {
299 ticks =
301 os::estd::chrono::systicks> (rel_time).count ());
302 }
303
305 res = nm_.timed_lock (ticks);
306 if (res == os::rtos::result::ok)
307 {
308 return true;
309 }
310 else if (res == ETIMEDOUT)
311 {
312 return false;
313 }
314
315 os::estd::__throw_system_error (static_cast<int> (res),
316 "timed_mutex try_lock failed");
317 return false;
318 }
319
320 template<typename Clock_T, typename Duration_T>
321 bool
323 const std::chrono::time_point<Clock_T, Duration_T>& abs_time)
324 {
325 using clock = Clock_T;
326
327 auto now = clock::now ();
328 while (now < abs_time)
329 {
330 if (try_lock_for (abs_time - now))
331 {
332 return true;
333 }
334 now = clock::now ();
335 }
336
337 return false;
338 }
339
340 // ==========================================================================
341 } /* namespace estd */
342} /* namespace os */
343
344#pragma GCC diagnostic pop
345
346#if defined(OS_HAS_STD_THREADS)
347
348namespace std
349{
355 // Redefine the objects in the std:: namespace.
356
357 using mutex = os::estd::mutex;
358 using recursive_mutex = os::estd::recursive_mutex;
359 using timed_mutex = os::estd::timed_mutex;
360 using recursive_timed_mutex = os::estd::recursive_timed_mutex;
361
365}
366
367#endif
368
369// ----------------------------------------------------------------------------
370
371#endif /* CMSIS_PLUS_ESTD_MUTEX_ */
native_type nm_
Definition mutex:108
mutex() noexcept
Definition mutex:204
mutex & operator=(const mutex &)=delete
void lock()
Definition mutex.cpp:45
native_handle_type native_handle()
Definition mutex:210
bool try_lock()
Definition mutex.cpp:57
void unlock()
Definition mutex.cpp:76
recursive_mutex(const recursive_mutex &)=delete
native_type nm_
Definition mutex:145
native_type * native_handle_type
Definition mutex:121
native_handle_type native_handle()
Definition mutex:226
recursive_timed_mutex(const recursive_timed_mutex &)=delete
bool try_lock_for(const std::chrono::duration< Rep_T, Period_T > &rel_time)
Definition mutex:292
bool try_lock_until(const std::chrono::time_point< Clock_T, Duration_T > &abs_time)
Definition mutex:322
bool try_lock_for(const std::chrono::duration< Rep_T, Period_T > &rel_time)
Definition mutex:238
bool try_lock_until(const std::chrono::time_point< Clock_T, Duration_T > &abs_time)
Definition mutex:268
timed_mutex(const timed_mutex &)=delete
POSIX compliant mutex.
Definition os-mutex.h:65
result_t timed_lock(clock::duration_t timeout)
Timed attempt to lock/acquire the mutex.
clock_t clock(void)
port::clock::duration_t duration_t
Type of variables holding clock durations.
Definition os-clocks.h:83
static const attributes_recursive initializer_recursive
Default recursive mutex initialiser.
Definition os-mutex.h:362
systick_clock::duration systicks
Definition chrono:117
constexpr std::enable_if< std::chrono::__is_duration< _To >::value, _To >::type ceil(std::chrono::duration< Rep_T, Period_T > d)
Definition chrono:278
void __throw_system_error(int ev, const char *what_arg)
@ ok
Function completed; no errors or events occurred.
Definition os-decls.h:195
uint32_t result_t
Type of values returned by RTOS functions.
Definition os-decls.h:110
System namespace.
Standard std namespace.
Single file µOS++ RTOS definitions.