Struct mycelium_util::sync::blocking::Mutex
pub struct Mutex<T, Lock = DefaultMutex> { /* private fields */ }
Expand description
A blocking mutual exclusion lock for protecting shared data.
Each mutex has a type parameter which represents
the data that it is protecting. The data can only be accessed through the
RAII guards returned from lock
and try_lock
, or within the closures
passed to with_lock
and try_with_lock
, which guarantees that
the data is only ever accessed when the mutex is locked.
Fairness
This is not a fair mutex.
Overriding mutex implementations
This type is generic over a Lock
type parameter which represents a raw
mutex implementation. By default, this is the DefaultMutex
. To construct
a new Mutex
with an alternative raw mutex implementation, use the
Mutex::new_with_raw_mutex
cosntructor. See the module-level documentation
on overriding mutex
implementations for
more details.
When Lock
implements the RawMutex
trait, the Mutex
type provides
the lock
and try_lock
methods, which return a RAII MutexGuard
,
similar to the std::sync::Mutex
API, in addition to the scoped
with_lock
and try_with_lock
methods. When Lock
only implements
ScopedRawMutex
, the Mutex
type provides only the scoped
with_lock
and try_with_lock
methods.
:warning: Note that DefaultMutex
does not implement RawMutex
, so
using the lock
and try_lock
RAII API requires selecting an
alternative RawMutex
implementation.
Loom-specific behavior
When cfg(loom)
is enabled, this mutex will use Loom’s simulated atomics,
checked UnsafeCell
, and simulated spin loop hints.
Implementations§
§impl<T> Mutex<T>
impl<T> Mutex<T>
pub const fn new(data: T) -> Mutex<T>
Available on non-loom
only.
pub const fn new(data: T) -> Mutex<T>
loom
only.Returns a new Mutex
protecting the provided data
.
The returned Mutex
is in an unlocked state, ready for use.
This constructor returns a mutex that uses the DefaultMutex
implementation. To use an alternative RawMutex
type, use the
new_with_raw_mutex
constructor, instead.
Examples
use maitake_sync::blocking::Mutex;
let mutex = Mutex::new(0);
§impl<T, Lock> Mutex<T, Lock>
impl<T, Lock> Mutex<T, Lock>
pub const fn new_with_raw_mutex(data: T, lock: Lock) -> Mutex<T, Lock>
Available on non-loom
only.
pub const fn new_with_raw_mutex(data: T, lock: Lock) -> Mutex<T, Lock>
loom
only.Returns a new Mutex
protecting the provided data
, using
lock
type parameter as the raw mutex implementation.
See the module-level documentation on overriding mutex implementations for more details.
The returned Mutex
is in an unlocked state, ready for use.
pub fn into_inner(self) -> T
pub fn into_inner(self) -> T
Consumes this Mutex
, returning the guarded data.
pub fn get_mut(&mut self) -> &mut T
pub fn get_mut(&mut self) -> &mut T
Returns a mutable reference to the underlying data.
Since this call borrows the Mutex
mutably, no actual locking needs to
take place – the mutable borrow statically guarantees no locks exist.
Examples
let mut lock = maitake_sync::blocking::Mutex::new(0);
lock.with_lock(|data| *data = 10);
assert_eq!(*lock.get_mut(), 10);
§impl<T, Lock> Mutex<T, Lock>where
Lock: ScopedRawMutex,
impl<T, Lock> Mutex<T, Lock>where
Lock: ScopedRawMutex,
pub fn with_lock<U>(&self, f: impl FnOnce(&mut T) -> U) -> U
pub fn with_lock<U>(&self, f: impl FnOnce(&mut T) -> U) -> U
Lock this Mutex
, blocking if it is not currently unlocked, and call
f()
with the locked data once the lock is acquired.
When the Mutex
is unlocked, this method locks it, calls f()
with the
data protected by the Mutex
, and then unlocks the Mutex
and returns
the result of f()
. If the Mutex
is locked, this method blocks until
it is unlocked, and then takes the lock.
To return immediately rather than blocking, use Mutex::try_with_lock
instead.
This method is available as long as the Mutex
’s Lock
type parameter
implements the ScopedRawMutex
trait. See the module-level
documentation on overriding mutex
implementations for
more details.
pub fn try_with_lock<U>(&self, f: impl FnOnce(&mut T) -> U) -> Option<U>
pub fn try_with_lock<U>(&self, f: impl FnOnce(&mut T) -> U) -> Option<U>
Attempt to lock this Mutex
without blocking and call f()
with the
locked data if the lock is acquired.
If the Mutex
is unlocked, this method locks it, calls f()
with the
data protected by the Mutex
, and then unlocks the Mutex
and returns
Some
(U)
. Otherwise, if the lock is already held, this method
returns None
immediately, without blocking.
To block until the Mutex
is unlocked instead of returning None
, use
Mutex::with_lock
instead.
This method is available as long as the Mutex
’s Lock
type parameter
implements the ScopedRawMutex
trait. See the module-level
documentation on overriding mutex
implementations for
more details.
Returns
§impl<T, Lock> Mutex<T, Lock>where
Lock: RawMutex,
impl<T, Lock> Mutex<T, Lock>where
Lock: RawMutex,
pub fn try_lock(&self) -> Option<MutexGuard<'_, T, Lock>>
pub fn try_lock(&self) -> Option<MutexGuard<'_, T, Lock>>
Attempts to acquire this lock without blocking
If the lock could not be acquired at this time, then None
is returned.
Otherwise, an RAII guard is returned. The lock will be unlocked when the
guard is dropped.
This function will never block.
This method is only availble if the Mutex
’s Lock
type parameter
implements the RawMutex
trait. See the module-level documentation
on overriding mutex
implementations for
more details.
pub fn lock(&self) -> MutexGuard<'_, T, Lock>
pub fn lock(&self) -> MutexGuard<'_, T, Lock>
Acquires a mutex, blocking until it is locked.
This function will block until the mutex is available to lock. Upon returning, the thread is the only thread with the lock held. An RAII guard is returned to allow scoped unlock of the lock. When the guard goes out of scope, the mutex will be unlocked.
This method is only availble if the Mutex
’s Lock
type parameter
implements the RawMutex
trait. See the module-level documentation
on overriding mutex
implementations for
more details.
pub unsafe fn force_unlock(&self)
pub unsafe fn force_unlock(&self)
Forcibly unlock the mutex.
If a lock is currently held, it will be released, regardless of who’s holding it. Of course, this is outrageously, disgustingly unsafe and you should never do it.
This method is only availble if the Mutex
’s Lock
type parameter
implements the RawMutex
trait. See the module-level documentation
on overriding mutex
implementations for
more details.
Safety
This deliberately violates mutual exclusion.
Only call this method when it is guaranteed that no stack frame that has previously locked the mutex will ever continue executing. Essentially, this is only okay to call when the kernel is oopsing and all code running on other cores has already been killed.
Trait Implementations§
§impl<T, Lock> Debug for Mutex<T, Lock>where
T: Debug,
Lock: ScopedRawMutex,
impl<T, Lock> Debug for Mutex<T, Lock>where
T: Debug,
Lock: ScopedRawMutex,
impl<T, Lock> Send for Mutex<T, Lock>
impl<T, Lock> Sync for Mutex<T, Lock>
A Mutex
is Sync
if T
is Send
and Lock
is Sync
.
T
must be Send
because shared references to the Mutex
allow mutable
access to T
(via a MutexGuard
or Mutex::with_lock
), which can be
used to move T
between threads using core::mem::replace
or similar.
T
does not need to be Sync
, and, in fact, a Mutex
is often used
to protect !Sync
data.
The Lock
type must be Sync
because sharing references to a mutex
implicitly share references to the Lock
type as well — locking the mutex
references it.