aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlix ANNERAUD <[email protected]>2025-03-17 20:03:36 +0100
committerAlix ANNERAUD <[email protected]>2025-03-17 20:03:36 +0100
commitbce15cc813f0fec7eaac1cb709706fb0f4c5e3b8 (patch)
tree66bbc8561254c1270e1f5b54cd6567d0b6fc70bc
parent41276de34fdc30ebb1c73d9aa3f1664cd7a26345 (diff)
Enhance RwLock documentation and add map methods for read and write guards to improve data access flexibility
-rw-r--r--embassy-sync/src/rwlock.rs63
1 files changed, 57 insertions, 6 deletions
diff --git a/embassy-sync/src/rwlock.rs b/embassy-sync/src/rwlock.rs
index 7f0bbec60..25c575925 100644
--- a/embassy-sync/src/rwlock.rs
+++ b/embassy-sync/src/rwlock.rs
@@ -11,7 +11,7 @@ use crate::blocking_mutex::raw::RawMutex;
11use crate::blocking_mutex::Mutex as BlockingMutex; 11use crate::blocking_mutex::Mutex as BlockingMutex;
12use crate::waitqueue::WakerRegistration; 12use crate::waitqueue::WakerRegistration;
13 13
14/// Error returned by [`RwLock::try_read_lock`] and [`RwLock::try_write_lock`] 14/// Error returned by [`RwLock::try_read`] and [`RwLock::try_write`] when the lock is already held.
15#[derive(PartialEq, Eq, Clone, Copy, Debug)] 15#[derive(PartialEq, Eq, Clone, Copy, Debug)]
16#[cfg_attr(feature = "defmt", derive(defmt::Format))] 16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17pub struct TryLockError; 17pub struct TryLockError;
@@ -24,7 +24,7 @@ struct State {
24 24
25/// Async read-write lock. 25/// Async read-write lock.
26/// 26///
27/// The read-write lock is generic over a blocking [`RawRwLock`](crate::blocking_mutex::raw_rwlock::RawRwLock). 27/// The read-write lock is generic over the raw mutex implementation `M` and the data `T` it protects.
28/// The raw read-write lock is used to guard access to the internal state. It 28/// The raw read-write lock is used to guard access to the internal state. It
29/// is held for very short periods only, while locking and unlocking. It is *not* held 29/// is held for very short periods only, while locking and unlocking. It is *not* held
30/// for the entire time the async RwLock is locked. 30/// for the entire time the async RwLock is locked.
@@ -307,6 +307,25 @@ where
307 rwlock: &'a RwLock<R, T>, 307 rwlock: &'a RwLock<R, T>,
308} 308}
309 309
310impl<'a, R, T> RwLockWriteGuard<'a, R, T>
311where
312 R: RawMutex,
313 T: ?Sized,
314{
315 /// Returns a locked view over a portion of the locked data.
316 pub fn map<U>(this: Self, fun: impl FnOnce(&mut T) -> &mut U) -> MappedRwLockWriteGuard<'a, R, U> {
317 let rwlock = this.rwlock;
318 let value = fun(unsafe { &mut *this.rwlock.inner.get() });
319 // Dont run the `drop` method for RwLockWriteGuard. The ownership of the underlying
320 // locked state is being moved to the returned MappedRwLockWriteGuard.
321 mem::forget(this);
322 MappedRwLockWriteGuard {
323 state: &rwlock.state,
324 value,
325 }
326 }
327}
328
310impl<'a, R, T> Drop for RwLockWriteGuard<'a, R, T> 329impl<'a, R, T> Drop for RwLockWriteGuard<'a, R, T>
311where 330where
312 R: RawMutex, 331 R: RawMutex,
@@ -366,8 +385,8 @@ where
366 } 385 }
367} 386}
368 387
369/// A handle to a held `Mutex` that has had a function applied to it via [`MutexGuard::map`] or 388/// A handle to a held `RwLock` that has had a function applied to it via [`RwLockReadGuard::map`] or
370/// [`MappedMutexGuard::map`]. 389/// [`MappedRwLockReadGuard::map`].
371/// 390///
372/// This can be used to hold a subfield of the protected data. 391/// This can be used to hold a subfield of the protected data.
373#[clippy::has_significant_drop] 392#[clippy::has_significant_drop]
@@ -380,6 +399,22 @@ where
380 value: *const T, 399 value: *const T,
381} 400}
382 401
402impl<'a, M, T> MappedRwLockReadGuard<'a, M, T>
403where
404 M: RawMutex,
405 T: ?Sized,
406{
407 /// Returns a locked view over a portion of the locked data.
408 pub fn map<U>(this: Self, fun: impl FnOnce(&T) -> &U) -> MappedRwLockReadGuard<'a, M, U> {
409 let rwlock = this.state;
410 let value = fun(unsafe { &*this.value });
411 // Dont run the `drop` method for RwLockReadGuard. The ownership of the underlying
412 // locked state is being moved to the returned MappedRwLockReadGuard.
413 mem::forget(this);
414 MappedRwLockReadGuard { state: rwlock, value }
415 }
416}
417
383impl<'a, M, T> Deref for MappedRwLockReadGuard<'a, M, T> 418impl<'a, M, T> Deref for MappedRwLockReadGuard<'a, M, T>
384where 419where
385 M: RawMutex, 420 M: RawMutex,
@@ -443,8 +478,8 @@ where
443 } 478 }
444} 479}
445 480
446/// A handle to a held `Mutex` that has had a function applied to it via [`MutexGuard::map`] or 481/// A handle to a held `RwLock` that has had a function applied to it via [`RwLockWriteGuard::map`] or
447/// [`MappedMutexGuard::map`]. 482/// [`MappedRwLockWriteGuard::map`].
448/// 483///
449/// This can be used to hold a subfield of the protected data. 484/// This can be used to hold a subfield of the protected data.
450#[clippy::has_significant_drop] 485#[clippy::has_significant_drop]
@@ -457,6 +492,22 @@ where
457 value: *mut T, 492 value: *mut T,
458} 493}
459 494
495impl<'a, M, T> MappedRwLockWriteGuard<'a, M, T>
496where
497 M: RawMutex,
498 T: ?Sized,
499{
500 /// Returns a locked view over a portion of the locked data.
501 pub fn map<U>(this: Self, fun: impl FnOnce(&mut T) -> &mut U) -> MappedRwLockWriteGuard<'a, M, U> {
502 let rwlock = this.state;
503 let value = fun(unsafe { &mut *this.value });
504 // Dont run the `drop` method for RwLockWriteGuard. The ownership of the underlying
505 // locked state is being moved to the returned MappedRwLockWriteGuard.
506 mem::forget(this);
507 MappedRwLockWriteGuard { state: rwlock, value }
508 }
509}
510
460impl<'a, M, T> Deref for MappedRwLockWriteGuard<'a, M, T> 511impl<'a, M, T> Deref for MappedRwLockWriteGuard<'a, M, T>
461where 512where
462 M: RawMutex, 513 M: RawMutex,