pub struct RwMutex<T: ?Sized> {
lock: AtomicUsize,
queue: WaitQueue,
val: UnsafeCell<T>,
}
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 point
Fields§
§lock: AtomicUsize
The internal representation of the mutex state is as follows:
- Bit 63: Writer mutex.
- Bit 62: Upgradeable reader mutex.
- Bit 61: Indicates if an upgradeable reader is being upgraded.
- Bits 60-0: Reader mutex count.
queue: WaitQueue
Threads that fail to acquire the mutex will sleep on this waitqueue.
val: UnsafeCell<T>
Implementations§
Source§impl<T: ?Sized> RwMutex<T>
impl<T: ?Sized> RwMutex<T>
Sourcepub fn read(&self) -> RwMutexReadGuard<'_, T>
pub 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 fn write(&self) -> RwMutexWriteGuard<'_, T>
pub 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 fn upread(&self) -> RwMutexUpgradeableGuard<'_, T>
pub 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 upgread method. However, only one upreader can exist at any time to avoid deadlock in the upgread method.
Sourcepub fn try_read(&self) -> Option<RwMutexReadGuard<'_, T>>
pub fn try_read(&self) -> Option<RwMutexReadGuard<'_, T>>
Attempts to acquire a read mutex.
This function will never sleep and will return immediately.
Sourcepub fn try_write(&self) -> Option<RwMutexWriteGuard<'_, T>>
pub fn try_write(&self) -> Option<RwMutexWriteGuard<'_, T>>
Attempts to acquire a write mutex.
This function will never sleep and will return immediately.
Sourcepub fn try_upread(&self) -> Option<RwMutexUpgradeableGuard<'_, T>>
pub 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: ?Sized + 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: ?Sized + 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>
impl<T> !UnwindSafe for RwMutex<T>
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> 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<T> Pointee for T
impl<T> Pointee for T
§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.