    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200

    use super::CriticalSection;
    use core::cell::{Ref, RefCell, RefMut, UnsafeCell};

    /// A mutex based on critical sections.
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use critical_section::Mutex;
    /// # use std::cell::Cell;
    ///
    /// 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.
    ///
    /// ```no_run
    /// # use critical_section::Mutex;
    /// # use std::cell::RefCell;
    ///
    /// 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);
    ///     })
    /// }
    /// ```
    ///
    /// [`std::sync::Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
    /// [interior mutability]: https://doc.rust-lang.org/reference/interior-mutability.html
    #[derive(Debug)]
    pub struct Mutex<T> {
        inner: UnsafeCell<T>,
    }

    impl<T> Mutex<T> {
        /// Creates a new mutex.
        #[inline]
        pub const fn new(value: T) -> Self {
            Mutex {
                inner: UnsafeCell::new(value),
            }
        }

        /// 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.
        #[inline]
        pub fn get_mut(&mut self) -> &mut T {
            unsafe { &mut *self.inner.get() }
        }

        /// Unwraps the contained value, consuming the mutex.
        #[inline]
        pub fn into_inner(self) -> T {
            self.inner.into_inner()
        }

        /// Borrows the data for the duration of the critical section.
        #[inline]
        pub fn borrow<'cs>(&'cs self, _cs: CriticalSection<'cs>) -> &'cs T {
            unsafe { &*self.inner.get() }
        }
    }

    impl<T> Mutex<RefCell<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.
        #[inline]
        #[track_caller]
        pub fn replace<'cs>(&'cs self, cs: CriticalSection<'cs>, t: T) -> T {
            self.borrow(cs).replace(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.
        #[inline]
        #[track_caller]
        pub fn replace_with<'cs, F>(&'cs self, cs: CriticalSection<'cs>, f: F) -> T
        where
            F: FnOnce(&mut T) -> T,
        {
            self.borrow(cs).replace_with(f)
        }

        /// 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.
        #[inline]
        #[track_caller]
        pub fn borrow_ref<'cs>(&'cs self, cs: CriticalSection<'cs>) -> Ref<'cs, T> {
            self.borrow(cs).borrow()
        }

        /// 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.
        #[inline]
        #[track_caller]
        pub fn borrow_ref_mut<'cs>(&'cs self, cs: CriticalSection<'cs>) -> RefMut<'cs, T> {
            self.borrow(cs).borrow_mut()
        }
    }

    impl<T: Default> Mutex<RefCell<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.
        #[inline]
        #[track_caller]
        pub fn take<'cs>(&'cs self, cs: CriticalSection<'cs>) -> T {
            self.borrow(cs).take()
        }
    }

    // NOTE A `Mutex` can be used as a channel so the protected data must be `Send`
    // to prevent sending non-Sendable stuff (e.g. access tokens) across different
    // threads.
    unsafe impl<T> Sync for Mutex<T> where T: Send {}

    /// ``` compile_fail
    /// fn bad(cs: critical_section::CriticalSection) -> &u32 {
    ///     let x = critical_section::Mutex::new(42u32);
    ///     x.borrow(cs)
    /// }
    /// ```
    #[cfg(doctest)]
    const BorrowMustNotOutliveMutexTest: () = ();