one_shot_mutex/unsync/
rwlock.rs
1use core::cell::Cell;
2
3use lock_api::{
4 GuardSend, RawRwLock, RawRwLockDowngrade, RawRwLockRecursive, RawRwLockUpgrade,
5 RawRwLockUpgradeDowngrade,
6};
7
8pub struct RawOneShotRwLock {
40 lock: Cell<usize>,
41}
42
43const SHARED: usize = 1 << 2;
45const UPGRADABLE: usize = 1 << 1;
47const EXCLUSIVE: usize = 1;
49
50impl RawOneShotRwLock {
51 pub const fn new() -> Self {
52 Self::INIT
53 }
54
55 #[inline]
56 fn over_state(&self, f: impl FnOnce(usize) -> usize) -> usize {
57 let old = self.lock.get();
58 self.lock.set(f(old));
59 old
60 }
61
62 #[inline]
63 fn is_locked_shared(&self) -> bool {
64 self.lock.get() & !(EXCLUSIVE | UPGRADABLE) != 0
65 }
66
67 #[inline]
68 fn is_locked_upgradable(&self) -> bool {
69 self.lock.get() & UPGRADABLE == UPGRADABLE
70 }
71
72 #[inline]
74 fn acquire_shared(&self) -> usize {
75 let value = self.over_state(|state| state + SHARED);
76
77 if value > usize::MAX / 2 {
79 self.over_state(|state| state - SHARED);
80 panic!("Too many shared locks, cannot safely proceed");
81 }
82
83 value
84 }
85}
86
87impl Default for RawOneShotRwLock {
88 fn default() -> Self {
89 Self::new()
90 }
91}
92
93unsafe impl RawRwLock for RawOneShotRwLock {
94 #[allow(clippy::declare_interior_mutable_const)]
95 const INIT: Self = Self { lock: Cell::new(0) };
96
97 type GuardMarker = GuardSend;
98
99 #[inline]
100 fn lock_shared(&self) {
101 assert!(
102 self.try_lock_shared(),
103 "called `lock_shared` on a `RawOneShotRwLock` that is already locked exclusively"
104 );
105 }
106
107 #[inline]
108 fn try_lock_shared(&self) -> bool {
109 let value = self.acquire_shared();
110
111 let acquired = value & EXCLUSIVE != EXCLUSIVE;
112
113 if !acquired {
114 unsafe {
115 self.unlock_shared();
116 }
117 }
118
119 acquired
120 }
121
122 #[inline]
123 unsafe fn unlock_shared(&self) {
124 debug_assert!(self.is_locked_shared());
125
126 self.over_state(|state| state - SHARED);
127 }
128
129 #[inline]
130 fn lock_exclusive(&self) {
131 assert!(
132 self.try_lock_exclusive(),
133 "called `lock_exclusive` on a `RawOneShotRwLock` that is already locked"
134 );
135 }
136
137 #[inline]
138 fn try_lock_exclusive(&self) -> bool {
139 let ok = self.lock.get() == 0;
140 if ok {
141 self.lock.set(EXCLUSIVE);
142 }
143 ok
144 }
145
146 #[inline]
147 unsafe fn unlock_exclusive(&self) {
148 debug_assert!(self.is_locked_exclusive());
149
150 self.over_state(|state| state & !EXCLUSIVE);
151 }
152
153 #[inline]
154 fn is_locked(&self) -> bool {
155 self.lock.get() != 0
156 }
157
158 #[inline]
159 fn is_locked_exclusive(&self) -> bool {
160 self.lock.get() & EXCLUSIVE == EXCLUSIVE
161 }
162}
163
164unsafe impl RawRwLockRecursive for RawOneShotRwLock {
165 #[inline]
166 fn lock_shared_recursive(&self) {
167 self.lock_shared();
168 }
169
170 #[inline]
171 fn try_lock_shared_recursive(&self) -> bool {
172 self.try_lock_shared()
173 }
174}
175
176unsafe impl RawRwLockDowngrade for RawOneShotRwLock {
177 #[inline]
178 unsafe fn downgrade(&self) {
179 self.acquire_shared();
181
182 unsafe {
183 self.unlock_exclusive();
184 }
185 }
186}
187
188unsafe impl RawRwLockUpgrade for RawOneShotRwLock {
189 #[inline]
190 fn lock_upgradable(&self) {
191 assert!(
192 self.try_lock_upgradable(),
193 "called `lock_upgradable` on a `RawOneShotRwLock` that is already locked upgradably or exclusively"
194 );
195 }
196
197 #[inline]
198 fn try_lock_upgradable(&self) -> bool {
199 let value = self.over_state(|state| state | UPGRADABLE);
200
201 let acquired = value & (UPGRADABLE | EXCLUSIVE) == 0;
202
203 if !acquired && value & UPGRADABLE == 0 {
204 unsafe {
205 self.unlock_upgradable();
206 }
207 }
208
209 acquired
210 }
211
212 #[inline]
213 unsafe fn unlock_upgradable(&self) {
214 debug_assert!(self.is_locked_upgradable());
215
216 self.over_state(|state| state & !UPGRADABLE);
217 }
218
219 #[inline]
220 unsafe fn upgrade(&self) {
221 assert!(
222 self.try_upgrade(),
223 "called `upgrade` on a `RawOneShotRwLock` that is also locked shared by others"
224 );
225 }
226
227 #[inline]
228 unsafe fn try_upgrade(&self) -> bool {
229 let ok = self.lock.get() == UPGRADABLE;
230 if ok {
231 self.lock.set(EXCLUSIVE);
232 }
233 ok
234 }
235}
236
237unsafe impl RawRwLockUpgradeDowngrade for RawOneShotRwLock {
238 #[inline]
239 unsafe fn downgrade_upgradable(&self) {
240 self.acquire_shared();
241
242 unsafe {
243 self.unlock_upgradable();
244 }
245 }
246
247 #[inline]
248 unsafe fn downgrade_to_upgradable(&self) {
249 debug_assert!(self.is_locked_exclusive());
250
251 self.over_state(|state| state ^ (UPGRADABLE | EXCLUSIVE));
252 }
253}
254
255pub type OneShotRwLock<T> = lock_api::RwLock<RawOneShotRwLock, T>;
257
258pub type OneShotRwLockReadGuard<'a, T> = lock_api::RwLockReadGuard<'a, RawOneShotRwLock, T>;
260
261pub type OneShotRwLockUpgradableReadGuard<'a, T> =
263 lock_api::RwLockUpgradableReadGuard<'a, RawOneShotRwLock, T>;
264
265pub type OneShotRwLockWriteGuard<'a, T> = lock_api::RwLockWriteGuard<'a, RawOneShotRwLock, T>;
267
268#[cfg(test)]
269mod tests {
270 use lock_api::RwLockUpgradableReadGuard;
271
272 use super::*;
273
274 #[test]
275 fn lock_exclusive() {
276 let lock = OneShotRwLock::new(42);
277 let mut guard = lock.write();
278 assert_eq!(*guard, 42);
279
280 *guard += 1;
281 drop(guard);
282 let guard = lock.write();
283 assert_eq!(*guard, 43);
284 }
285
286 #[test]
287 #[should_panic]
288 fn lock_exclusive_panic() {
289 let lock = OneShotRwLock::new(42);
290 let _guard = lock.write();
291 let _guard2 = lock.write();
292 }
293
294 #[test]
295 #[should_panic]
296 fn lock_exclusive_shared_panic() {
297 let lock = OneShotRwLock::new(42);
298 let _guard = lock.write();
299 let _guard2 = lock.read();
300 }
301
302 #[test]
303 fn try_lock_exclusive() {
304 let lock = OneShotRwLock::new(42);
305 let mut guard = lock.try_write().unwrap();
306 assert_eq!(*guard, 42);
307 assert!(lock.try_write().is_none());
308
309 *guard += 1;
310 drop(guard);
311 let guard = lock.try_write().unwrap();
312 assert_eq!(*guard, 43);
313 }
314
315 #[test]
316 fn lock_shared() {
317 let lock = OneShotRwLock::new(42);
318 let guard = lock.read();
319 assert_eq!(*guard, 42);
320 let guard2 = lock.read();
321 assert_eq!(*guard2, 42);
322 }
323
324 #[test]
325 #[should_panic]
326 fn lock_shared_panic() {
327 let lock = OneShotRwLock::new(42);
328 let _guard = lock.write();
329 let _guard2 = lock.read();
330 }
331
332 #[test]
333 fn try_lock_shared() {
334 let lock = OneShotRwLock::new(42);
335 let guard = lock.try_read().unwrap();
336 assert_eq!(*guard, 42);
337 assert!(lock.try_write().is_none());
338
339 let guard2 = lock.try_read().unwrap();
340 assert_eq!(*guard2, 42);
341 }
342
343 #[test]
344 fn lock_upgradable() {
345 let lock = OneShotRwLock::new(42);
346 let guard = lock.upgradable_read();
347 assert_eq!(*guard, 42);
348 assert!(lock.try_write().is_none());
349
350 let mut upgraded = RwLockUpgradableReadGuard::upgrade(guard);
351 *upgraded += 1;
352 drop(upgraded);
353 let guard2 = lock.upgradable_read();
354 assert_eq!(*guard2, 43);
355 }
356
357 #[test]
358 #[should_panic]
359 fn lock_upgradable_panic() {
360 let lock = OneShotRwLock::new(42);
361 let _guard = lock.upgradable_read();
362 let _guard2 = lock.upgradable_read();
363 }
364
365 #[test]
366 #[should_panic]
367 fn lock_upgradable_write_panic() {
368 let lock = OneShotRwLock::new(42);
369 let _guard = lock.write();
370 let _guard2 = lock.upgradable_read();
371 }
372
373 #[test]
374 fn try_lock_upgradable() {
375 let lock = OneShotRwLock::new(42);
376 let guard = lock.try_upgradable_read().unwrap();
377 assert_eq!(*guard, 42);
378 assert!(lock.try_write().is_none());
379
380 let mut upgraded = RwLockUpgradableReadGuard::try_upgrade(guard).unwrap();
381 *upgraded += 1;
382 drop(upgraded);
383 let guard2 = lock.try_upgradable_read().unwrap();
384 assert_eq!(*guard2, 43);
385 }
386
387 #[test]
388 #[should_panic]
389 fn upgrade_panic() {
390 let lock = OneShotRwLock::new(42);
391 let guard = lock.upgradable_read();
392 let _guard2 = lock.read();
393 let _guard3 = RwLockUpgradableReadGuard::upgrade(guard);
394 }
395}