FreeRTOScpp
Loading...
Searching...
No Matches
ReadWrite.h
Go to the documentation of this file.
1/**
2 * @file ReadWrite.h
3 * @brief FreeRTOS Read/Write Lock Wrapper
4 *
5 * This file contains a set of lightweight wrappers for mutexes using FreeRTOS
6 *
7 * @warning This is a fairly new module, and may not be fully tested
8 *
9 * @copyright (c) 2007-2024 Richard Damon
10 * @author Richard Damon <richard.damon@gmail.com>
11 * @parblock
12 * MIT License:
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 * of this software and associated documentation files (the "Software"), to deal
16 * in the Software without restriction, including without limitation the rights
17 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18 * copies of the Software, and to permit persons to whom the Software is
19 * furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30 * THE SOFTWARE.
31 *
32 * It is requested (but not required by license) that any bugs found or
33 * improvements made be shared, preferably to the author.
34 * @endparblock
35 *
36 * @ingroup FreeRTOSCpp
37 */
38
39#ifndef READWRITE_H
40#define READWRITE_H
41
42#include "EventCpp.h"
43#include "TaskCPP.h"
44#include "Lock.h"
45
46#if FREERTOSCPP_USE_NAMESPACE
47namespace FreeRTOScpp {
48#endif
49
50class ReadWriteLock;
51
52/**
53 * Read-Write Lock Read Side Lockability Base
54 *
55 * Base class to provide Read side Lockability
56*/
57class Reader : public Lockable {
58 friend class ReadWriteLock;
59private:
60 Reader() {}
61public:
62 bool take(TickType_t wait) override;
63 bool give() override;
64};
65
66/**
67 * Read-Write Write Side Lockability Base
68 */
69class Writer : public Lockable {
70 friend class ReadWriteLock;
71private:
72 Writer() {}
73public:
74 bool take(TickType_t wait) override;
75 bool give() override;
76
77};
78
79
80/**
81 * Read/Write Lock control
82 *
83 * States:
84 * + Free: readCount == 0
85 * + Read: readCount > 0, reserved == 0
86 * + Reserved: readCount > 0, reserved != 0
87 * + Write: readCount == -1, reserved == 0
88 * + Upgraded: readCount == -1, reserved != 0
89 *
90 * @dot
91 digraph states {
92 compound=true;
93 rankdir="LR";
94 subgraph cluster_0 {
95 Free;
96 }
97
98 subgraph cluster_1 {
99 Read;
100 Reserved;
101 label="Read";
102
103 }
104
105 subgraph cluster_2 {
106 Write;
107 Upgraded;
108 label="Write";
109 }
110
111 Free:w -> Read [color=green, label="readLock"];
112 Read -> Free:sw [color=red, label="readUnlock"];
113 Free:ne -> Reserved:se [color=green, label="reserveLock"];
114 Read:e -> Reserved:w [color=green, label="reserveRequest"];
115 Reserved:nw -> Read:ne [color=red, label="reserveRelease"];
116 Reserved:sw -> Free:nw [color=red, label="readUnlock"];
117 Free:e -> Write [color=green, label="writeLock"];
118 Reserved:e -> Upgraded:w [color=green, label="writeLock"];
119 Write -> Free:se [color=red, label="writeUnlock"];
120 Upgraded:nw -> Reserved:ne [color=red, label="writeUnlock"];
121 }
122 * @enddot
123 * @warning This is a fairly new module, and may not be fully tested
124 */
125class ReadWriteLock : public Reader, public Writer {
126public:
129
130 /**
131 * Get Read Lockable
132 *
133 * @returns a lockable object for using with Read Locks.
134 */
135 Reader& rlock() { return *this; }
136 /**
137 * Get Write Lockable
138 *
139 * @returns a lockable object for using with Write Locks
140 */
141 Writer& wlock() { return *this; }
142
143 /**
144 * ReadLock
145 *
146 * Get a read lock.
147 * @param wait The maximum number of ticks to wait to get the lock
148 * @returns true if the read lock has been granted
149 *
150 * Algorithm:
151 *
152 * + Loop
153 * + If readCount >=0 and our priority > writeReq
154 * + Increment readCount
155 * + return true
156 * + if Time has expired:
157 * + return false
158 * + else wait a tick for read_bit event.
159 */
160 bool readLock(TickType_t wait = portMAX_DELAY);
161 /**
162 * Get an upgradable Read Lock
163 *
164 * like readLock, but add reserved == nullptr to the conditions.
165 * On success will set reserved to our task handle.
166 *
167 * Only one task can reserve this, as if two are in this state they will deadlock when
168 * they both try to upgrade
169 */
170 bool reservedLock(TickType_t wait = portMAX_DELAY);
171 /**
172 * Task with a Read Lock request upgrade to a reserved lock.
173 * If no reservation current, will be granted, if reservation present, will be rejected.
174 *
175 * Does not check if this task has a read lock, but that is assumed.
176 */
177 bool requestReserved();
178 /**
179 * If we have a reserved lock, down grade to just a read lock
180 */
181 bool releaseReserved();
182 /**
183 * Remove our lock. If we reserved the upgrade, release that.
184 */
185 bool readUnlock();
186
187 /**
188 * Take the write lock, requires readCount to be 0, or 1 if we reserved the upgrade.
189 */
190 bool writeLock(TickType_t wait = portMAX_DELAY);
191 /**
192 * Release the write lock. If we upgraded go back to a reserved lock which will need to be unlocked.
193 */
194 bool writeUnlock();
195
196#if FREERTOSCPP_USE_CHRONO
197 bool readLock(Time_ms delay_ms) { return readLock(ms2ticks(delay_ms)); }
198 bool reservedLock(Time_ms delay_ms) { return reservedLock(ms2ticks(delay_ms)); }
199 bool writeLock(Time_ms delay_ms) { return writeLock(ms2ticks(delay_ms)); }
200#endif
201protected:
203 /**
204 * Count of Read Locks
205 *
206 * If 0, then lock is free
207 * if >0, lock is in read mode and is the count of the number of read locks granted
208 * if <0, loci is in write mode.
209 */
210 int readCount = 0;
211 /**
212 * Reserved Lock indicator
213 *
214 * If nullptr, then no reservedLock are currently in existence, so a reservedLock can be granted
215 *
216 * Else, TaskHandle of the task that has reserved the right to upgrade to a write lock.
217 */
218 TaskHandle_t reserved = nullptr;
219 /**
220 * Write Request Pending Priority.
221 *
222 * If in Read mode, and a task with priority below writeReq
223 */
224 int writeReq = -1;
225};
226
227#if FREERTOSCPP_USE_NAMESPACE
228}
229#endif
230
231#endif
FreeRTOS Event Group Wrapper.
FreeRTOS Lock wrapper.
FreeRTOS Task Wrapper.
Definition EventCPP.h:69
A Base class to provide block based locking capability.
Definition Lock.h:58
Read/Write Lock control.
Definition ReadWrite.h:125
EventGroup event
Definition ReadWrite.h:202
Reader & rlock()
Get Read Lockable.
Definition ReadWrite.h:135
Writer & wlock()
Get Write Lockable.
Definition ReadWrite.h:141
Read-Write Lock Read Side Lockability Base.
Definition ReadWrite.h:57
Reader()
Definition ReadWrite.h:60
Read-Write Write Side Lockability Base.
Definition ReadWrite.h:69
Writer()
Definition ReadWrite.h:72
Definition FreeRTOScpp.h:74