pub struct RwMutex<T> { /* private fields */ }Expand description
A mutex that provides data access to either one writer or many readers.
§Overview
This mutex allows for multiple readers, or at most one writer to access at any point in time. The writer of this mutex has exclusive access to modify the underlying data, while the readers are allowed shared and read-only access.
The writing and reading portions cannot be active simultaneously, when one portion is in progress, the other portion will sleep. This is suitable for scenarios where the mutex is expected to be held for a period of time, which can avoid wasting CPU resources.
This implementation provides the upgradeable read mutex (upread mutex).
The upread mutex can be upgraded to write mutex atomically, useful in
scenarios where a decision to write is made after reading.
The type parameter T represents the data that this mutex is protecting.
It is necessary for T to satisfy Send to be shared across tasks and
Sync to permit concurrent access via readers. The Deref method (and
DerefMut for the writer) is implemented for the RAII guards returned
by the locking methods, which allows for the access to the protected data
while the mutex is held.
§Usage
The mutex can be used in scenarios where data needs to be read frequently but written to occasionally.
Use upread mutex in scenarios where related checking is performed before
modification to effectively avoid deadlocks and improve efficiency.
§Safety
Avoid using RwMutex in an interrupt context, as it may result in sleeping
and never being awakened.
§Examples
use ostd::sync::RwMutex;
let mutex = RwMutex::new(5)
// many read mutexes can be held at once
{
let r1 = mutex.read();
let r2 = mutex.read();
assert_eq!(*r1, 5);
assert_eq!(*r2, 5);
// Upgradeable read mutex can share access to data with read mutexes
let r3 = mutex.upread();
assert_eq!(*r3, 5);
drop(r1);
drop(r2);
// read mutexes are dropped at this point
// An upread mutex can only be upgraded successfully after all the
// read mutexes are released, otherwise it will spin-wait.
let mut w1 = r3.upgrade();
*w1 += 1;
assert_eq!(*w1, 6);
} // upread mutex are dropped at this point
{
// Only one write mutex can be held at a time
let mut w2 = mutex.write();
*w2 += 1;
assert_eq!(*w2, 7);
} // write mutex is dropped at this pointImplementations§
Source§impl<T> RwMutex<T>
impl<T> RwMutex<T>
Sourcepub closed spec fn core_token_id(self) -> Loc
pub closed spec fn core_token_id(self) -> Loc
Sourcepub closed spec fn upread_retract_token_id(self) -> Loc
pub closed spec fn upread_retract_token_id(self) -> Loc
Sourcepub closed spec fn read_guard_token_id(self) -> Loc
pub closed spec fn read_guard_token_id(self) -> Loc
Source§impl<T> RwMutex<T>
impl<T> RwMutex<T>
Sourcepub exec fn read(&self) -> RwMutexReadGuard<'_, T>
pub exec fn read(&self) -> RwMutexReadGuard<'_, T>
Acquires a read mutex and sleep until it can be acquired.
The calling thread will sleep until there are no writers or upgrading
upreaders present. The implementation of WaitQueue guarantees the
order in which other concurrent readers or writers waiting simultaneously
will acquire the mutex.
Sourcepub exec fn write(&self) -> RwMutexWriteGuard<'_, T>
pub exec fn write(&self) -> RwMutexWriteGuard<'_, T>
Acquires a write mutex and sleep until it can be acquired.
The calling thread will sleep until there are no writers, upreaders,
or readers present. The implementation of WaitQueue guarantees the
order in which other concurrent readers or writers waiting simultaneously
will acquire the mutex.
Sourcepub exec fn upread(&self) -> RwMutexUpgradeableGuard<'_, T>
pub exec fn upread(&self) -> RwMutexUpgradeableGuard<'_, T>
Acquires a upread mutex and sleep until it can be acquired.
The calling thread will sleep until there are no writers or upreaders present.
The implementation of WaitQueue guarantees the order in which other concurrent
readers or writers waiting simultaneously will acquire the mutex.
Upreader will not block new readers until it tries to upgrade. Upreader and reader do not differ before invoking the upgrade method. However, only one upreader can exist at any time to avoid deadlock in the upgrade method.
Sourcepub exec fn try_read(&self) -> Option<RwMutexReadGuard<'_, T>>
pub exec fn try_read(&self) -> Option<RwMutexReadGuard<'_, T>>
Attempts to acquire a read mutex.
This function will never sleep and will return immediately.
Sourcepub exec fn try_write(&self) -> Option<RwMutexWriteGuard<'_, T>>
pub exec fn try_write(&self) -> Option<RwMutexWriteGuard<'_, T>>
Attempts to acquire a write mutex.
This function will never sleep and will return immediately.
Sourcepub exec fn try_upread(&self) -> Option<RwMutexUpgradeableGuard<'_, T>>
pub exec fn try_upread(&self) -> Option<RwMutexUpgradeableGuard<'_, T>>
Attempts to acquire a upread mutex.
This function will never sleep and will return immediately.
Trait Implementations§
impl<T: Send> Send for RwMutex<T>
Because there can be more than one readers to get the T’s immutable ref, so T must be Sync to guarantee the sharing safety.
impl<T: Send + Sync> Sync for RwMutex<T>
Auto Trait Implementations§
impl<T> !Freeze for RwMutex<T>
impl<T> !RefUnwindSafe for RwMutex<T>
impl<T> Unpin for RwMutex<T>where
T: Unpin,
impl<T> UnsafeUnpin for RwMutex<T>where
T: UnsafeUnpin,
impl<T> UnwindSafe for RwMutex<T>where
T: UnwindSafe + RefUnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T, VERUS_SPEC__A> FromSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: From<T>,
impl<T, VERUS_SPEC__A> FromSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: From<T>,
fn obeys_from_spec() -> bool
fn from_spec(v: T) -> VERUS_SPEC__A
§impl<T, VERUS_SPEC__A> IntoSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: Into<T>,
impl<T, VERUS_SPEC__A> IntoSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: Into<T>,
fn obeys_into_spec() -> bool
fn into_spec(self) -> T
§impl<T, U> IntoSpecImpl<U> for Twhere
U: From<T>,
impl<T, U> IntoSpecImpl<U> for Twhere
U: From<T>,
fn obeys_into_spec() -> bool
fn into_spec(self) -> U
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.impl<A> SpecEq<&A> for Awhere
A: ?Sized,
impl<A> SpecEq<&mut A> for Awhere
A: ?Sized,
impl<A> SpecEq<A> for Awhere
A: ?Sized,
impl<A> SpecEq<Ghost<A>> for A
impl<A> SpecEq<Tracked<A>> for A
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.