IntrOS
Loading...
Searching...
No Matches
osrwlock.h
1/******************************************************************************
2
3 @file IntrOS: osrwlock.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_RWL_H
33#define __INTROS_RWL_H
34
35#include "oskernel.h"
36#include "osclock.h"
37
43
44/* -------------------------------------------------------------------------- */
45
46#define RDR_LIMIT ( 0U-1 )
47
51
52typedef struct __rwl rwl_t;
53
54struct __rwl
55{
56 obj_t obj;
57
58 tsk_t * queue;
59 bool write;
60 unsigned count;
61};
62
63typedef struct __rwl rwl_id [];
64
65/******************************************************************************
66 *
67 * Name : _RWL_INIT
68 *
69 * Description : create and initialize a read/write lock object
70 *
71 * Parameters : none
72 *
73 * Return : read/write lock object
74 *
75 * Note : for internal use
76 *
77 ******************************************************************************/
78
79#define _RWL_INIT() { _OBJ_INIT(), NULL, false, 0 }
80
87#define OS_RWL( rwl ) \
88 rwl_t rwl[] = { _RWL_INIT() }
89
90/** static alias of OS_RWL() */
91#define static_RWL( rwl ) \
92 static rwl_t rwl[] = { _RWL_INIT() }
93
101
102#ifndef __cplusplus
103#define RWL_INIT() \
104 _RWL_INIT()
105#endif
106
114
115#ifndef __cplusplus
116#define RWL_CREATE() \
117 { RWL_INIT () }
118/** alias of RWL_CREATE() */
119#define RWL_NEW \
120 RWL_CREATE
121#endif
122
123#ifdef __cplusplus
124extern "C" {
125#endif
126
133void rwl_init( rwl_t *rwl );
134
143void rwl_reset( rwl_t *rwl );
144
146__STATIC_INLINE
147void rwl_kill( rwl_t *rwl ) { rwl_reset(rwl); }
148
159int rwl_takeRead( rwl_t *rwl );
160
162__STATIC_INLINE
163int rwl_tryLockRead( rwl_t *rwl ) { return rwl_takeRead(rwl); }
164
179int rwl_waitReadFor( rwl_t *rwl, cnt_t delay );
180
193int rwl_waitReadUntil( rwl_t *rwl, cnt_t time );
194
204
205__STATIC_INLINE
206int rwl_waitRead( rwl_t *rwl ) { return rwl_waitReadFor(rwl, INFINITE); }
207
209__STATIC_INLINE
210int rwl_lockRead( rwl_t *rwl ) { return rwl_waitRead(rwl); }
211
218void rwl_giveRead( rwl_t *rwl );
219
221__STATIC_INLINE
222void rwl_unlockRead( rwl_t *rwl ) { rwl_giveRead(rwl); }
223
234int rwl_takeWrite( rwl_t *rwl );
235
237__STATIC_INLINE
238int rwl_tryLockWrite( rwl_t *rwl ) { return rwl_takeWrite(rwl); }
239
254int rwl_waitWriteFor( rwl_t *rwl, cnt_t delay );
255
268int rwl_waitWriteUntil( rwl_t *rwl, cnt_t time );
269
279
280__STATIC_INLINE
281int rwl_waitWrite( rwl_t *rwl ) { return rwl_waitWriteFor(rwl, INFINITE); }
282
284__STATIC_INLINE
285int rwl_lockWrite( rwl_t *rwl ) { return rwl_waitWrite(rwl); }
286
293void rwl_giveWrite( rwl_t *rwl );
294
296__STATIC_INLINE
297void rwl_unlockWrite( rwl_t *rwl ) { rwl_giveWrite(rwl); }
298
299#ifdef __cplusplus
300}
301#endif
302
303/* -------------------------------------------------------------------------- */
304
305#if defined(__cplusplus)
306namespace intros {
307
312struct RWLock : public __rwl
313{
315 constexpr
316 RWLock(): __rwl _RWL_INIT() {}
317
318 ~RWLock() { assert(__rwl::write == false && __rwl::count == 0); }
319
320 /// move constructor
321 RWLock( RWLock&& _src ): __rwl(_src)
322 {
323 assert(_src.write == false && _src.count == 0 && _src.obj.queue == nullptr && _src.queue == nullptr);
324 }
325
326 RWLock( const RWLock& ) = delete;
327 RWLock& operator=( RWLock&& ) = delete;
328 RWLock& operator=( const RWLock& ) = delete;
330 void reset () { rwl_reset (this); }
331 void kill () { rwl_kill (this); }
332 int takeRead () { return rwl_takeRead (this); }
333 int tryLockRead () { return rwl_tryLockRead (this); }
334 template<typename T>
335 int waitReadFor ( const T& _delay ) { return rwl_waitReadFor (this, Clock::count(_delay)); }
336 template<typename T>
337 int waitReadUntil ( const T& _time ) { return rwl_waitReadUntil (this, Clock::until(_time)); }
338 int waitRead () { return rwl_waitRead (this); }
339 int lockRead () { return rwl_lockRead (this); }
340 void giveRead () { rwl_giveRead (this); }
341 void unlockRead () { rwl_unlockRead (this); }
342 int takeWrite () { return rwl_takeWrite (this); }
343 int tryLockWrite () { return rwl_tryLockWrite (this); }
344 template<typename T>
345 int waitWriteFor ( const T& _delay ) { return rwl_waitWriteFor (this, Clock::count(_delay)); }
346 template<typename T>
347 int waitWriteUntil( const T& _time ) { return rwl_waitWriteUntil(this, Clock::until(_time)); }
348 int waitWrite () { return rwl_waitWrite (this); }
349 int lockWrite () { return rwl_lockWrite (this); }
350 void giveWrite () { rwl_giveWrite (this); }
351 void unlockWrite () { rwl_unlockWrite (this); }
352};
353
361struct ReadLock
362{
364 explicit
365 ReadLock( RWLock& _rwl ): lck_(&_rwl)
366 {
367 int result = lck_->lockRead();
368 assert(result == E_SUCCESS || result == E_STOPPED);
369 if (result != E_SUCCESS)
370 lck_ = nullptr; // nothing to release
371 }
372
373 ~ReadLock()
374 {
375 if (lck_ != nullptr)
376 lck_->unlockRead();
377 }
378
379 /// move constructor
380 ReadLock( ReadLock&& _src ): lck_(_src.lck_)
381 {
382 _src.lck_ = nullptr;
383 }
384
386 bool ownsLock() const { return lck_ != nullptr; }
387
388 explicit
389 operator bool() const { return ownsLock(); }
390
391 ReadLock( const ReadLock& ) = delete;
392 ReadLock& operator=( ReadLock&& ) = delete;
393 ReadLock& operator=( const ReadLock& ) = delete;
394
395 private:
396 RWLock *lck_;
397};
398
406struct WriteLock
407{
409 explicit
410 WriteLock( RWLock& _rwl ): lck_(&_rwl)
411 {
412 int result = lck_->lockWrite();
413 assert(result == E_SUCCESS || result == E_STOPPED);
414 if (result != E_SUCCESS)
415 lck_ = nullptr; // nothing to release
416 }
417
418 ~WriteLock()
419 {
420 if (lck_ != nullptr)
421 lck_->unlockWrite();
422 }
423
424 /// move constructor
425 WriteLock( WriteLock&& _src ): lck_(_src.lck_)
426 {
427 _src.lck_ = nullptr;
428 }
429
431 bool ownsLock() const { return lck_ != nullptr; }
432
433 explicit
434 operator bool() const { return ownsLock(); }
435
436 WriteLock( const WriteLock& ) = delete;
437 WriteLock& operator=( WriteLock&& ) = delete;
438 WriteLock& operator=( const WriteLock& ) = delete;
439
440 private:
441 RWLock *lck_;
442};
443
444} // namespace
445#endif//__cplusplus
446
447/* -------------------------------------------------------------------------- */
448
450
451#endif//__INTROS_RWL_H
#define INFINITE
infinite waiting
Definition osbase.h:250
@ 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
void rwl_unlockRead(rwl_t *rwl)
alias of rwl_giveRead()
Definition osrwlock.h:221
int rwl_waitReadFor(rwl_t *rwl, cnt_t delay)
try to lock the reader, wait for given duration of time if the reader can't be locked immediately
int rwl_waitWriteUntil(rwl_t *rwl, cnt_t time)
try to lock the writer, wait until given timepoint if the writer can't be locked immediately
int rwl_lockRead(rwl_t *rwl)
alias of rwl_waitRead()
Definition osrwlock.h:209
int rwl_tryLockWrite(rwl_t *rwl)
alias of rwl_takeWrite()
Definition osrwlock.h:237
void rwl_unlockWrite(rwl_t *rwl)
alias of rwl_giveWrite()
Definition osrwlock.h:296
int rwl_waitRead(rwl_t *rwl)
try to lock the reader, wait indefinitely if the reader can't be locked immediately
Definition osrwlock.h:205
void rwl_giveWrite(rwl_t *rwl)
unlock the writer
int rwl_lockWrite(rwl_t *rwl)
alias of rwl_waitWrite()
Definition osrwlock.h:284
int rwl_waitWriteFor(rwl_t *rwl, cnt_t delay)
try to lock the writer, wait for given duration of time if the writer can't be locked immediately
int rwl_waitWrite(rwl_t *rwl)
try to lock the writer, wait indefinitely if the writer can't be locked immediately
Definition osrwlock.h:280
void rwl_giveRead(rwl_t *rwl)
unlock the reader
int rwl_waitReadUntil(rwl_t *rwl, cnt_t time)
try to lock the reader, wait until given timepoint if the reader can't be locked immediately
void rwl_kill(rwl_t *rwl)
alias of rwl_reset()
Definition osrwlock.h:146
void rwl_init(rwl_t *rwl)
initialize a read/write lock object
int rwl_takeRead(rwl_t *rwl)
try to lock the reader, don't wait if the reader can't be locked immediately
int rwl_tryLockRead(rwl_t *rwl)
alias of rwl_takeRead()
Definition osrwlock.h:162
int rwl_takeWrite(rwl_t *rwl)
try to lock the writer, don't wait if the writer can't be locked immediately
void rwl_reset(rwl_t *rwl)
reset the read/write lock object and wake up all waiting tasks with 'E_STOPPED' event value
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 read/write lock object
Definition osrwlock.h:312
int waitWrite()
rwl_waitWrite()
Definition osrwlock.h:347
int lockWrite()
rwl_lockWrite()
Definition osrwlock.h:348
int tryLockRead()
rwl_tryLockRead()
Definition osrwlock.h:332
void reset()
rwl_reset()
Definition osrwlock.h:329
int tryLockWrite()
rwl_tryLockWrite()
Definition osrwlock.h:342
int waitWriteFor(const T &_delay)
rwl_waitWriteFor()
Definition osrwlock.h:344
int waitRead()
rwl_waitRead()
Definition osrwlock.h:337
void giveWrite()
rwl_giveWrite()
Definition osrwlock.h:349
int lockRead()
rwl_lockRead()
Definition osrwlock.h:338
int waitReadUntil(const T &_time)
rwl_waitReadUntil()
Definition osrwlock.h:336
void unlockRead()
rwl_unlockRead()
Definition osrwlock.h:340
int waitWriteUntil(const T &_time)
rwl_waitWriteUntil()
Definition osrwlock.h:346
void kill()
rwl_kill()
Definition osrwlock.h:330
void giveRead()
rwl_giveRead()
Definition osrwlock.h:339
int takeRead()
rwl_takeRead()
Definition osrwlock.h:331
constexpr RWLock()
constructor, see the constructor parameters of the class
Definition osrwlock.h:315
int takeWrite()
rwl_takeWrite()
Definition osrwlock.h:341
void unlockWrite()
rwl_unlockWrite()
Definition osrwlock.h:350
int waitReadFor(const T &_delay)
rwl_waitReadFor()
Definition osrwlock.h:334
create and initialize a read guard object
Definition osrwlock.h:361
bool ownsLock() const
true: the lock is held by the guard; false: the lock was reset while waiting (or the guard was moved)
Definition osrwlock.h:385
ReadLock(RWLock &_rwl)
constructor, see the constructor parameters of the class
Definition osrwlock.h:364
create and initialize a write guard object
Definition osrwlock.h:406
bool ownsLock() const
true: the lock is held by the guard; false: the lock was reset while waiting (or the guard was moved)
Definition osrwlock.h:430
WriteLock(RWLock &_rwl)
constructor, see the constructor parameters of the class
Definition osrwlock.h:409