# Struct critical_section::Mutex

source ·

    pub struct Mutex<T> { /* private fields */ }

Expand description

A mutex based on critical sections.

## Example

    static FOO: Mutex<Cell<i32>> = Mutex::new(Cell::new(42));

    fn main() {
        critical_section::with(|cs| {
            FOO.borrow(cs).set(43);
        });
    }

    fn interrupt_handler() {
        let _x = critical_section::with(|cs| FOO.borrow(cs).get());
    }

## Design

`std::sync::Mutex` has two purposes. It converts types that are [`Send`] but not [`Sync`] into types that are both; and it provides interior mutability. `critical_section::Mutex`, on the other hand, only adds `Sync`. It does not provide interior mutability.

This was a conscious design choice. It is possible to create multiple `CriticalSection` tokens, either by nesting critical sections or `Copy`ing an existing token. As a result, it would not be sound for `Mutex::borrow` to return `&mut T`, because there would be nothing to prevent calling `borrow` multiple times to create aliased `&mut T` references.

The solution is to include a runtime check to ensure that each resource is borrowed only once. This is what `std::sync::Mutex` does. However, this is a runtime cost that may not be required in all circumstances. For instance, `Mutex<Cell<T>>` never needs to create `&mut T` or equivalent.

If `&mut T` is needed, the simplest solution is to use `Mutex<RefCell<T>>`, which is the closest analogy to `std::sync::Mutex`. [`RefCell`] inserts the exact runtime check necessary to guarantee that the `&mut T` reference is unique.

To reduce verbosity when using `Mutex<RefCell<T>>`, we reimplement some of `RefCell`’s methods on it directly.

    static FOO: Mutex<RefCell<i32>> = Mutex::new(RefCell::new(42));

    fn main() {
        critical_section::with(|cs| {
            // Instead of calling this
            let _ = FOO.borrow(cs).take();
            // Call this
            let _ = FOO.take(cs);
            // `RefCell::borrow` and `RefCell::borrow_mut` are renamed to
            // `borrow_ref` and `borrow_ref_mut` to avoid name collisions
            let _: &mut i32 = &mut *FOO.borrow_ref_mut(cs);
        })
    }

## Implementations§

source§

### impl<T> Mutex<T>

source

#### pub const fn new(value: T) -> Self

Creates a new mutex.

source

#### pub fn get_mut(&mut self) -> &mut T

Gets a mutable reference to the contained value when the mutex is already uniquely borrowed.

This does not require locking or a critical section since it takes `&mut self`, which guarantees unique ownership already. Care must be taken when using this method to unsafely access `static mut` variables, appropriate fences must be used to prevent unwanted optimizations.

source

#### pub fn into_inner(self) -> T

Unwraps the contained value, consuming the mutex.

source

#### pub fn borrow<'cs>(&'cs self, _cs: CriticalSection<'cs>) -> &'cs T

Borrows the data for the duration of the critical section.

source§

### impl<T> Mutex<RefCell<T>>

source

#### pub fn replace<'cs>(&'cs self, cs: CriticalSection<'cs>, t: T) -> T

Borrow the data and call [`RefCell::replace`]

This is equivalent to `self.borrow(cs).replace(t)`

##### Panics

This call could panic. See the documentation for [`RefCell::replace`] for more details.

source

#### pub fn replace_with<'cs, F>(&'cs self, cs: CriticalSection<'cs>, f: F) -> Twhere F: FnOnce(&mut T) -> T,

Borrow the data and call [`RefCell::replace_with`]

This is equivalent to `self.borrow(cs).replace_with(f)`

##### Panics

This call could panic. See the documentation for [`RefCell::replace_with`] for more details.

source

#### pub fn borrow_ref<'cs>(&'cs self, cs: CriticalSection<'cs>) -> Ref<'cs, T>

Borrow the data and call [`RefCell::borrow`]

This is equivalent to `self.borrow(cs).borrow()`

##### Panics

This call could panic. See the documentation for [`RefCell::borrow`] for more details.

source

#### pub fn borrow_ref_mut<'cs>( &'cs self, cs: CriticalSection<'cs> ) -> RefMut<'cs, T>

Borrow the data and call [`RefCell::borrow_mut`]

This is equivalent to `self.borrow(cs).borrow_mut()`

##### Panics

This call could panic. See the documentation for [`RefCell::borrow_mut`] for more details.

source§

### impl<T: Default> Mutex<RefCell<T>>

source

#### pub fn take<'cs>(&'cs self, cs: CriticalSection<'cs>) -> T

Borrow the data and call [`RefCell::take`]

This is equivalent to `self.borrow(cs).take()`

##### Panics

This call could panic. See the documentation for [`RefCell::take`] for more details.

## Trait Implementations§

source§

### impl<T: Debug> Debug for Mutex<T>

source§

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

Formats the value using the given formatter. Read more
source§

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

## Auto Trait Implementations§

§

### impl<T> !RefUnwindSafe for Mutex<T>

§

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

§

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

§

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

## Blanket Implementations§

§

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

§

#### fn type_id(&self) -> TypeId

Gets the `TypeId` of `self`. Read more
§

### impl<T> Borrow<T> for Twhere T: ?Sized,

§

#### fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

### impl<T> BorrowMut<T> for Twhere T: ?Sized,

§

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

Mutably borrows from an owned value. Read more
§

### impl<T> From<T> for T

§

#### fn from(t: T) -> T

Returns the argument unchanged.

§

### impl<T, U> Into<U> for Twhere U: From<T>,

§

#### fn into(self) -> U

Calls `U::from(self)`.

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

§

### impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

#### type Error = Infallible

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

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

Performs the conversion.
§

### impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

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

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

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

Performs the conversion.