proxima_primitives/sync/rwlock.rs
1//! `proxima::sync::RwLock` — async reader-writer lock, shape-
2//! compatible with `tokio::sync::RwLock`. Backed by
3//! `async_lock::RwLock` with a thin newtype that reshapes
4//! `try_read` / `try_write` from `Option` (async-lock) to
5//! `Result<_, TryLockError>` (tokio). The async-lock variant is
6//! fair (FIFO across readers and writers) and provides the same
7//! `read(&self).await` / `write(&self).await` shape as tokio.
8//!
9//! # Non-coverage
10//!
11//! - `read_owned() -> OwnedRwLockReadGuard<T>` /
12//! `write_owned() -> OwnedRwLockWriteGuard<T>` — Arc-coupled owned
13//! guards. tokio offers these for guards that outlive a borrow of
14//! the lock; `async_lock::RwLock` has no analog. Mirror of the
15//! `lock_owned` gap on Mutex.
16//! - `try_read_owned() -> Result<OwnedRwLockReadGuard<T>, TryLockError>`
17//! and `try_write_owned()` — same.
18//! - `read_arc()` / `write_arc()` — async-lock's Arc-coupled variants;
19//! not re-exported because no caller currently needs them.
20//! - `RwLock::blocking_read()` / `RwLock::blocking_write()` — sync-
21//! context acquisition. Don't use sync acquisition from async code.
22
23pub use async_lock::{RwLockReadGuard, RwLockWriteGuard};
24
25use crate::sync::TryLockError;
26
27/// Async reader-writer lock matching `tokio::sync::RwLock`'s shape.
28#[derive(Debug, Default)]
29pub struct RwLock<T: ?Sized>(async_lock::RwLock<T>);
30
31impl<T> RwLock<T> {
32 /// New lock containing `value`.
33 #[must_use]
34 pub fn new(value: T) -> Self {
35 Self(async_lock::RwLock::new(value))
36 }
37
38 /// Consume the lock, returning the inner value.
39 pub fn into_inner(self) -> T {
40 self.0.into_inner()
41 }
42}
43
44impl<T: ?Sized> RwLock<T> {
45 /// Acquire shared read access asynchronously.
46 pub async fn read(&self) -> RwLockReadGuard<'_, T> {
47 self.0.read().await
48 }
49
50 /// Acquire exclusive write access asynchronously.
51 pub async fn write(&self) -> RwLockWriteGuard<'_, T> {
52 self.0.write().await
53 }
54
55 /// Try to acquire a read guard without waiting.
56 pub fn try_read(&self) -> Result<RwLockReadGuard<'_, T>, TryLockError> {
57 self.0
58 .try_read()
59 .ok_or_else(crate::sync::mutex::try_lock_error)
60 }
61
62 /// Try to acquire a write guard without waiting.
63 pub fn try_write(&self) -> Result<RwLockWriteGuard<'_, T>, TryLockError> {
64 self.0
65 .try_write()
66 .ok_or_else(crate::sync::mutex::try_lock_error)
67 }
68
69 /// Mutable access without locking — `&mut self` proves exclusivity
70 /// statically.
71 pub fn get_mut(&mut self) -> &mut T {
72 self.0.get_mut()
73 }
74}