Struct maitake::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>

pub const fn new(data: T) -> Mutex<T>

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>

pub const fn new_with_raw_mutex(data: T, lock: Lock) -> Mutex<T, Lock>

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

Consumes this Mutex, returning the guarded data.

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,

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>

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
  • Some(U) if the lock was acquired, containing the result of f().
  • None if the lock is currently held and could not be acquired without blocking.
§

impl<T, Lock> Mutex<T, Lock>
where Lock: RawMutex,

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>

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)

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,

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl<T, Lock> Default for Mutex<T, Lock>
where T: Default, Lock: Default,

§

fn default() -> Mutex<T, Lock>

Returns the “default value” for a type. Read more
§

impl<T, Lock> Send for Mutex<T, Lock>
where T: Send, Lock: Send,

§

impl<T, Lock> Sync for Mutex<T, Lock>
where T: Send, Lock: Sync,

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.

Auto Trait Implementations§

§

impl<T, Lock = DefaultMutex> !RefUnwindSafe for Mutex<T, Lock>

§

impl<T, Lock> Unpin for Mutex<T, Lock>
where Lock: Unpin, T: Unpin,

§

impl<T, Lock> UnwindSafe for Mutex<T, Lock>
where Lock: UnwindSafe, T: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more