IntrOS
Loading...
Searching...
No Matches
osmutex.h
1/******************************************************************************
2
3 @file IntrOS: osmutex.h
4 @author Rajmund Szymanski
5 @date 17.11.2025
6 @brief This file contains definitions for IntrOS.
7
8 ******************************************************************************
9
10 Copyright (c) 2018-2022 Rajmund Szymanski. All rights reserved.
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to
14 deal in the Software without restriction, including without limitation the
15 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 sell copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included
20 in all copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 IN THE SOFTWARE.
29
30 ******************************************************************************/
31
32#ifndef __INTROS_MTX_H
33#define __INTROS_MTX_H
34
35#include "oskernel.h"
36#include "osclock.h"
37
43
47
48struct __mtx
49{
50 obj_t obj;
51
52 tsk_t * owner;
53 mtx_t * list;
54};
55
56typedef struct __mtx mtx_id [];
57
58/******************************************************************************
59 *
60 * Name : _MTX_INIT
61 *
62 * Description : create and initialize a mutex object
63 *
64 * Parameters : none
65 *
66 * Return : mutex object
67 *
68 * Note : for internal use
69 *
70 ******************************************************************************/
71
72#define _MTX_INIT() { _OBJ_INIT(), NULL, NULL }
73
80#define OS_MTX( mtx ) \
81 mtx_t mtx[] = { _MTX_INIT() }
82
83/** static alias of OS_MTX() */
84#define static_MTX( mtx ) \
85 static mtx_t mtx[] = { _MTX_INIT() }
86
94
95#ifndef __cplusplus
96#define MTX_INIT() \
97 _MTX_INIT()
98#endif
99
107
108#ifndef __cplusplus
109#define MTX_CREATE() \
110 { MTX_INIT () }
111/** alias of MTX_CREATE() */
112#define MTX_NEW \
113 MTX_CREATE
114#endif
115
116#ifdef __cplusplus
117extern "C" {
118#endif
119
126void mtx_init( mtx_t *mtx );
127
136void mtx_reset( mtx_t *mtx );
137
139__STATIC_INLINE
140void mtx_kill( mtx_t *mtx ) { mtx_reset(mtx); }
141
153int mtx_take( mtx_t *mtx );
154
156__STATIC_INLINE
157int mtx_tryLock( mtx_t *mtx ) { return mtx_take(mtx); }
158
174int mtx_waitFor( mtx_t *mtx, cnt_t delay );
175
189int mtx_waitUntil( mtx_t *mtx, cnt_t time );
190
201
202__STATIC_INLINE
203int mtx_wait( mtx_t *mtx ) { return mtx_waitFor(mtx, INFINITE); }
204
206__STATIC_INLINE
207int mtx_lock( mtx_t *mtx ) { return mtx_wait(mtx); }
208
219int mtx_give( mtx_t *mtx );
220
222__STATIC_INLINE
223int mtx_unlock( mtx_t *mtx ) { return mtx_give(mtx); }
224
225#ifdef __cplusplus
226}
227#endif
228
229/* -------------------------------------------------------------------------- */
230
231#if defined(__cplusplus)
232namespace intros {
233
238struct Mutex : public __mtx
239{
241 constexpr
242 Mutex(): __mtx _MTX_INIT() {}
243
244 ~Mutex() { assert(__mtx::owner == nullptr); }
245
246 /// move constructor
247 Mutex( Mutex&& _src ): __mtx(_src)
248 {
249 assert(_src.owner == nullptr && _src.obj.queue == nullptr);
250 }
251
252 Mutex( const Mutex& ) = delete;
253 Mutex& operator=( Mutex&& ) = delete;
254 Mutex& operator=( const Mutex& ) = delete;
256 void reset () { mtx_reset (this); }
257 void kill () { mtx_kill (this); }
258 int take () { return mtx_take (this); }
259 int tryLock () { return mtx_tryLock (this); }
260 template<typename T>
261 int waitFor ( const T& _delay ) { return mtx_waitFor (this, Clock::count(_delay)); }
262 template<typename T>
263 int waitUntil( const T& _time ) { return mtx_waitUntil(this, Clock::until(_time)); }
264 int wait () { return mtx_wait (this); }
265 int lock () { return mtx_lock (this); }
266 int give () { return mtx_give (this); }
267 int unlock () { return mtx_unlock (this); }
268};
269
274struct LockGuard
275{
277 explicit
278 LockGuard( Mutex& _mtx ): mtx_(&_mtx)
279 {
280 int result = mtx_->lock();
281 assert(result == E_SUCCESS || result == E_STOPPED);
282 if (result != E_SUCCESS)
283 mtx_ = nullptr; // nothing to release
284 }
285
286 ~LockGuard()
287 {
288 if (mtx_ == nullptr)
289 return;
290
291 int result = mtx_->unlock();
292 assert(result == E_SUCCESS);
293 (void) result;
294 }
295
296 /// move constructor
297 LockGuard( LockGuard&& _src ): mtx_(_src.mtx_)
298 {
299 _src.mtx_ = nullptr;
300 }
301
303 bool ownsLock() const { return mtx_ != nullptr; }
304
305 explicit
306 operator bool() const { return ownsLock(); }
307
308 LockGuard( const LockGuard& ) = delete;
309 LockGuard& operator=( LockGuard&& ) = delete;
310 LockGuard& operator=( const LockGuard& ) = delete;
311
312 private:
313 Mutex *mtx_;
314};
315
320struct UniqueLock
321{
323 explicit
324 UniqueLock( Mutex& _mtx ): mtx_(&_mtx), locked_(false)
325 {
326 lock();
327 }
328
330 template<typename T>
331 UniqueLock( Mutex& _mtx, const T& _delay ): mtx_(&_mtx), locked_(false)
332 {
333 waitFor(_delay);
334 }
335
336 /// move constructor
337 UniqueLock( UniqueLock&& _src ): mtx_(_src.mtx_), locked_(_src.locked_)
338 {
339 _src.mtx_ = nullptr;
340 _src.locked_ = false;
341 }
342
344 {
345 unlock();
346 }
347
349 UniqueLock() = default;
350 UniqueLock( const UniqueLock& ) = delete;
351 UniqueLock& operator=( const UniqueLock& ) = delete;
352
353 /// unlock the held mutex and take over the mutex of _src
354 UniqueLock& operator=( UniqueLock&& _src )
355 {
356 unlock();
357
358 mtx_ = _src.mtx_;
359 locked_ = _src.locked_;
360
361 _src.mtx_ = nullptr;
362 _src.locked_ = false;
363
364 return *this;
365 }
366
367 /// try to lock the mutex, don't wait; true: the mutex is locked
368 bool tryLock()
369 {
370 if (mtx_ == nullptr || locked_)
371 return false;
372
373 int result = mtx_->tryLock();
374 assert(result == E_SUCCESS || result == E_TIMEOUT);
375 locked_ = result == E_SUCCESS;
376 return locked_;
377 }
378
380 template<typename T>
381 bool waitFor( const T& _delay )
382 {
383 if (mtx_ == nullptr || locked_)
384 return false;
385
386 int result = mtx_->waitFor(_delay);
387 assert(result == E_SUCCESS || result == E_TIMEOUT || result == E_STOPPED);
388 locked_ = result == E_SUCCESS;
389 return locked_;
390 }
391
393 template<typename T>
394 bool waitUntil( const T& _time )
395 {
396 if (mtx_ == nullptr || locked_)
397 return false;
398
399 int result = mtx_->waitUntil(_time);
400 assert(result == E_SUCCESS || result == E_TIMEOUT || result == E_STOPPED);
401 locked_ = result == E_SUCCESS;
402 return locked_;
403 }
404
405 /// lock the mutex, wait indefinitely; true: the mutex is locked
406 bool lock()
407 {
408 if (mtx_ == nullptr || locked_)
409 return false;
410
411 int result = mtx_->lock();
412 assert(result == E_SUCCESS || result == E_STOPPED);
413 locked_ = result == E_SUCCESS;
414 return locked_;
415 }
416
417 /// unlock the mutex; true: the mutex was unlocked
418 bool unlock()
419 {
420 if (mtx_ == nullptr || !locked_)
421 return false;
422
423 int result = mtx_->unlock();
424 assert(result == E_SUCCESS);
425 locked_ = false;
426 return result == E_SUCCESS;
427 }
428
429 /// true: the mutex is locked by the object
430 bool ownsLock() const
431 {
432 return locked_;
433 }
434
436 explicit
437 operator bool() const
438 {
439 return ownsLock();
440 }
441
442 /// release the mutex without unlocking it, return the mutex
443 Mutex* release()
444 {
445 Mutex* result = mtx_;
446
447 mtx_ = nullptr;
448 locked_ = false;
449
450 return result;
451 }
452
453 /// associated mutex
454 Mutex* mutex() const
455 {
456 return mtx_;
457 }
458
459 private:
460 Mutex *mtx_ = nullptr;
461 bool locked_ = false;
462};
463
464} // namespace
465#endif//__cplusplus
466
467/* -------------------------------------------------------------------------- */
468
470
471#endif//__INTROS_MTX_H
#define INFINITE
infinite waiting
Definition osbase.h:250
@ E_TIMEOUT
process was released as a result of the end of the timer countdown
Definition osbase.h:153
@ E_SUCCESS
process was released as a result of taking the supervising object
Definition osbase.h:150
@ E_STOPPED
process was released as a result of reset the supervising object
Definition osbase.h:152
int mtx_tryLock(mtx_t *mtx)
alias of mtx_take()
Definition osmutex.h:156
void mtx_reset(mtx_t *mtx)
reset the mutex object and wake up all waiting tasks with 'E_STOPPED' event value
int mtx_give(mtx_t *mtx)
try to unlock the mutex object (only owner task can unlock mutex object), don't wait if the mutex obj...
void mtx_init(mtx_t *mtx)
initialize a mutex object
int mtx_take(mtx_t *mtx)
try to lock the mutex object, don't wait if the mutex object can't be locked immediately
int mtx_lock(mtx_t *mtx)
alias of mtx_wait()
Definition osmutex.h:206
void mtx_kill(mtx_t *mtx)
alias of mtx_reset()
Definition osmutex.h:139
int mtx_wait(mtx_t *mtx)
try to lock the mutex object, wait indefinitely if the mutex object can't be locked immediately
Definition osmutex.h:202
int mtx_waitUntil(mtx_t *mtx, cnt_t time)
try to lock the mutex object, wait until given timepoint if the mutex object can't be locked immediat...
int mtx_waitFor(mtx_t *mtx, cnt_t delay)
try to lock the mutex object, wait for given duration of time if the mutex object can't be locked imm...
int mtx_unlock(mtx_t *mtx)
alias of mtx_give()
Definition osmutex.h:222
static constexpr rep until(const std::chrono::time_point< Clock, _Duration > &_time)
time point in ticks, rounded up to whole ticks (only a time point of this clock)
Definition osclock.h:109
static constexpr rep count(const std::chrono::duration< _Rep, _Period > &_delay)
delay in ticks, rounded up to whole ticks; negative delay: IMMEDIATE, delay out of range: INFINITE
Definition osclock.h:102
create and initialize a lock guard object
Definition osmutex.h:274
bool ownsLock() const
true: the mutex is locked by the guard; false: the mutex was reset while waiting (or the guard was mo...
Definition osmutex.h:302
LockGuard(Mutex &_mtx)
constructor, see the constructor parameters of the class
Definition osmutex.h:277
create and initialize a mutex object
Definition osmutex.h:238
int wait()
mtx_wait()
Definition osmutex.h:263
int tryLock()
mtx_tryLock()
Definition osmutex.h:258
int take()
mtx_take()
Definition osmutex.h:257
int lock()
mtx_lock()
Definition osmutex.h:264
int waitFor(const T &_delay)
mtx_waitFor()
Definition osmutex.h:260
int waitUntil(const T &_time)
mtx_waitUntil()
Definition osmutex.h:262
void reset()
mtx_reset()
Definition osmutex.h:255
constexpr Mutex()
constructor, see the constructor parameters of the class
Definition osmutex.h:241
void kill()
mtx_kill()
Definition osmutex.h:256
int give()
mtx_give()
Definition osmutex.h:265
int unlock()
mtx_unlock()
Definition osmutex.h:266
create and initialize a unique lock object
Definition osmutex.h:320
bool waitUntil(const T &_time)
try to lock the mutex, wait until given timepoint; true: the mutex is locked
Definition osmutex.h:393
bool unlock()
unlock the mutex; true: the mutex was unlocked
Definition osmutex.h:417
Mutex * release()
release the mutex without unlocking it, return the mutex
Definition osmutex.h:442
bool lock()
lock the mutex, wait indefinitely; true: the mutex is locked
Definition osmutex.h:405
UniqueLock(Mutex &_mtx)
constructor, see the constructor parameters of the class
Definition osmutex.h:323
UniqueLock()=default
default constructor
bool waitFor(const T &_delay)
try to lock the mutex, wait for given duration of time; true: the mutex is locked
Definition osmutex.h:380
bool tryLock()
try to lock the mutex, don't wait; true: the mutex is locked
Definition osmutex.h:367
Mutex * mutex() const
associated mutex
Definition osmutex.h:453
bool ownsLock() const
true: the mutex is locked by the object
Definition osmutex.h:429