1 use super::CriticalSection; 2 use core::cell::{Ref, RefCell, RefMut, UnsafeCell}; 3 4 /// A mutex based on critical sections. 5 /// 6 /// # Example 7 /// 8 /// ```no_run 9 /// # use critical_section::Mutex; 10 /// # use std::cell::Cell; 11 /// 12 /// static FOO: Mutex<Cell<i32>> = Mutex::new(Cell::new(42)); 13 /// 14 /// fn main() { 15 /// critical_section::with(|cs| { 16 /// FOO.borrow(cs).set(43); 17 /// }); 18 /// } 19 /// 20 /// fn interrupt_handler() { 21 /// let _x = critical_section::with(|cs| FOO.borrow(cs).get()); 22 /// } 23 /// ``` 24 /// 25 /// 26 /// # Design 27 /// 28 /// [`std::sync::Mutex`] has two purposes. It converts types that are [`Send`] 29 /// but not [`Sync`] into types that are both; and it provides 30 /// [interior mutability]. `critical_section::Mutex`, on the other hand, only adds 31 /// `Sync`. It does *not* provide interior mutability. 32 /// 33 /// This was a conscious design choice. It is possible to create multiple 34 /// [`CriticalSection`] tokens, either by nesting critical sections or `Copy`ing 35 /// an existing token. As a result, it would not be sound for [`Mutex::borrow`] 36 /// to return `&mut T`, because there would be nothing to prevent calling 37 /// `borrow` multiple times to create aliased `&mut T` references. 38 /// 39 /// The solution is to include a runtime check to ensure that each resource is 40 /// borrowed only once. This is what `std::sync::Mutex` does. However, this is 41 /// a runtime cost that may not be required in all circumstances. For instance, 42 /// `Mutex<Cell<T>>` never needs to create `&mut T` or equivalent. 43 /// 44 /// If `&mut T` is needed, the simplest solution is to use `Mutex<RefCell<T>>`, 45 /// which is the closest analogy to `std::sync::Mutex`. [`RefCell`] inserts the 46 /// exact runtime check necessary to guarantee that the `&mut T` reference is 47 /// unique. 48 /// 49 /// To reduce verbosity when using `Mutex<RefCell<T>>`, we reimplement some of 50 /// `RefCell`'s methods on it directly. 51 /// 52 /// ```no_run 53 /// # use critical_section::Mutex; 54 /// # use std::cell::RefCell; 55 /// 56 /// static FOO: Mutex<RefCell<i32>> = Mutex::new(RefCell::new(42)); 57 /// 58 /// fn main() { 59 /// critical_section::with(|cs| { 60 /// // Instead of calling this 61 /// let _ = FOO.borrow(cs).take(); 62 /// // Call this 63 /// let _ = FOO.take(cs); 64 /// // `RefCell::borrow` and `RefCell::borrow_mut` are renamed to 65 /// // `borrow_ref` and `borrow_ref_mut` to avoid name collisions 66 /// let _: &mut i32 = &mut *FOO.borrow_ref_mut(cs); 67 /// }) 68 /// } 69 /// ``` 70 /// 71 /// [`std::sync::Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html 72 /// [interior mutability]: https://doc.rust-lang.org/reference/interior-mutability.html 73 #[derive(Debug)] 74 pub struct Mutex<T> { 75 // The `UnsafeCell` is not strictly necessary here: In theory, just using `T` should 76 // be fine. 77 // However, without `UnsafeCell`, the compiler may use niches inside `T`, and may 78 // read the niche value _without locking the mutex_. As we don't provide interior 79 // mutability, this is still not violating any aliasing rules and should be perfectly 80 // fine. But as the cost of adding `UnsafeCell` is very small, we add it out of 81 // cautiousness, just in case the reason `T` is not `Sync` in the first place is 82 // something very obscure we didn't consider. 83 inner: UnsafeCell<T>, 84 } 85 86 impl<T> Mutex<T> { 87 /// Creates a new mutex. 88 #[inline] new(value: T) -> Self89 pub const fn new(value: T) -> Self { 90 Mutex { 91 inner: UnsafeCell::new(value), 92 } 93 } 94 95 /// Gets a mutable reference to the contained value when the mutex is already uniquely borrowed. 96 /// 97 /// This does not require locking or a critical section since it takes `&mut self`, which 98 /// guarantees unique ownership already. Care must be taken when using this method to 99 /// **unsafely** access `static mut` variables, appropriate fences must be used to prevent 100 /// unwanted optimizations. 101 #[inline] get_mut(&mut self) -> &mut T102 pub fn get_mut(&mut self) -> &mut T { 103 unsafe { &mut *self.inner.get() } 104 } 105 106 /// Unwraps the contained value, consuming the mutex. 107 #[inline] into_inner(self) -> T108 pub fn into_inner(self) -> T { 109 self.inner.into_inner() 110 } 111 112 /// Borrows the data for the duration of the critical section. 113 #[inline] borrow<'cs>(&'cs self, _cs: CriticalSection<'cs>) -> &'cs T114 pub fn borrow<'cs>(&'cs self, _cs: CriticalSection<'cs>) -> &'cs T { 115 unsafe { &*self.inner.get() } 116 } 117 } 118 119 impl<T> Mutex<RefCell<T>> { 120 /// Borrow the data and call [`RefCell::replace`] 121 /// 122 /// This is equivalent to `self.borrow(cs).replace(t)` 123 /// 124 /// # Panics 125 /// 126 /// This call could panic. See the documentation for [`RefCell::replace`] 127 /// for more details. 128 #[inline] 129 #[track_caller] replace<'cs>(&'cs self, cs: CriticalSection<'cs>, t: T) -> T130 pub fn replace<'cs>(&'cs self, cs: CriticalSection<'cs>, t: T) -> T { 131 self.borrow(cs).replace(t) 132 } 133 134 /// Borrow the data and call [`RefCell::replace_with`] 135 /// 136 /// This is equivalent to `self.borrow(cs).replace_with(f)` 137 /// 138 /// # Panics 139 /// 140 /// This call could panic. See the documentation for 141 /// [`RefCell::replace_with`] for more details. 142 #[inline] 143 #[track_caller] replace_with<'cs, F>(&'cs self, cs: CriticalSection<'cs>, f: F) -> T where F: FnOnce(&mut T) -> T,144 pub fn replace_with<'cs, F>(&'cs self, cs: CriticalSection<'cs>, f: F) -> T 145 where 146 F: FnOnce(&mut T) -> T, 147 { 148 self.borrow(cs).replace_with(f) 149 } 150 151 /// Borrow the data and call [`RefCell::borrow`] 152 /// 153 /// This is equivalent to `self.borrow(cs).borrow()` 154 /// 155 /// # Panics 156 /// 157 /// This call could panic. See the documentation for [`RefCell::borrow`] 158 /// for more details. 159 #[inline] 160 #[track_caller] borrow_ref<'cs>(&'cs self, cs: CriticalSection<'cs>) -> Ref<'cs, T>161 pub fn borrow_ref<'cs>(&'cs self, cs: CriticalSection<'cs>) -> Ref<'cs, T> { 162 self.borrow(cs).borrow() 163 } 164 165 /// Borrow the data and call [`RefCell::borrow_mut`] 166 /// 167 /// This is equivalent to `self.borrow(cs).borrow_mut()` 168 /// 169 /// # Panics 170 /// 171 /// This call could panic. See the documentation for [`RefCell::borrow_mut`] 172 /// for more details. 173 #[inline] 174 #[track_caller] borrow_ref_mut<'cs>(&'cs self, cs: CriticalSection<'cs>) -> RefMut<'cs, T>175 pub fn borrow_ref_mut<'cs>(&'cs self, cs: CriticalSection<'cs>) -> RefMut<'cs, T> { 176 self.borrow(cs).borrow_mut() 177 } 178 } 179 180 impl<T: Default> Mutex<RefCell<T>> { 181 /// Borrow the data and call [`RefCell::take`] 182 /// 183 /// This is equivalent to `self.borrow(cs).take()` 184 /// 185 /// # Panics 186 /// 187 /// This call could panic. See the documentation for [`RefCell::take`] 188 /// for more details. 189 #[inline] 190 #[track_caller] take<'cs>(&'cs self, cs: CriticalSection<'cs>) -> T191 pub fn take<'cs>(&'cs self, cs: CriticalSection<'cs>) -> T { 192 self.borrow(cs).take() 193 } 194 } 195 196 // NOTE A `Mutex` can be used as a channel so the protected data must be `Send` 197 // to prevent sending non-Sendable stuff (e.g. access tokens) across different 198 // threads. 199 unsafe impl<T> Sync for Mutex<T> where T: Send {} 200 201 /// ``` compile_fail 202 /// fn bad(cs: critical_section::CriticalSection) -> &u32 { 203 /// let x = critical_section::Mutex::new(42u32); 204 /// x.borrow(cs) 205 /// } 206 /// ``` 207 #[cfg(doctest)] 208 const BorrowMustNotOutliveMutexTest: () = (); 209