1#![no_std]
43#![deny(missing_docs)]
44
45use core::cell::RefCell;
46use core::ops::{Deref, DerefMut};
47
48pub mod prelude {
93 pub use crate::Mutex;
94
95 macro_rules! lock {
96 ($e:ident, $fun:block) => {
97 $e.lock(|$e| $fun )
98 };
99 ($e:ident, $($es:ident),+, $fun:block) => {
100 $e.lock(|$e| lock!($($es),*, $fun))
101 };
102 }
103
104 macro_rules! make_tuple_impl {
105 ($name:ident, $($es:ident),+) => {
106 pub trait $name {
108 $(
109 type $es;
111 )*
112
113 fn lock<R>(&mut self, f: impl FnOnce($(&mut Self::$es),*) -> R) -> R;
115 }
116
117 impl<$($es),+> $name for ($($es,)+)
118 where
119 $($es: crate::Mutex),*
120 {
121 $(
122 type $es = $es::Data;
123 )*
124
125 #[allow(non_snake_case)]
126 fn lock<R>(&mut self, f: impl FnOnce($(&mut Self::$es),*) -> R) -> R {
127 let ($(
128 $es,
129 )*) = self;
130
131 lock!($($es),*, { f($($es),*) })
132 }
133 }
134 };
135 }
136
137 make_tuple_impl!(TupleExt01, T1);
139 make_tuple_impl!(TupleExt02, T1, T2);
140 make_tuple_impl!(TupleExt03, T1, T2, T3);
141 make_tuple_impl!(TupleExt04, T1, T2, T3, T4);
142 make_tuple_impl!(TupleExt05, T1, T2, T3, T4, T5);
143 make_tuple_impl!(TupleExt06, T1, T2, T3, T4, T5, T6);
144 make_tuple_impl!(TupleExt07, T1, T2, T3, T4, T5, T6, T7);
145 make_tuple_impl!(TupleExt08, T1, T2, T3, T4, T5, T6, T7, T8);
146 make_tuple_impl!(TupleExt09, T1, T2, T3, T4, T5, T6, T7, T8, T9);
147 make_tuple_impl!(TupleExt10, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
148 make_tuple_impl!(TupleExt11, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
149 make_tuple_impl!(TupleExt12, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
150}
151
152pub trait Mutex {
155 type Data;
157
158 fn lock<R>(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R;
160}
161
162impl<L> Mutex for &'_ mut L
164where
165 L: Mutex,
166{
167 type Data = L::Data;
168
169 fn lock<R>(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R {
170 L::lock(self, f)
171 }
172}
173
174impl<T> Mutex for &'_ RefCell<T> {
176 type Data = T;
177
178 fn lock<R>(&mut self, f: impl FnOnce(&mut T) -> R) -> R {
179 f(&mut self.borrow_mut())
180 }
181}
182
183#[derive(Debug)]
187pub struct Exclusive<'a, T>(&'a mut T);
188
189impl<'a, T> Exclusive<'a, T> {
190 pub fn new(data: &'a mut T) -> Self {
192 Exclusive(data)
193 }
194
195 pub fn into_inner(self) -> &'a mut T {
197 self.0
198 }
199}
200
201impl<'a, T> From<&'a mut T> for Exclusive<'a, T> {
202 fn from(data: &'a mut T) -> Self {
203 Exclusive(data)
204 }
205}
206
207impl<'a, T> Deref for Exclusive<'a, T> {
208 type Target = T;
209
210 fn deref(&self) -> &T {
211 self.0
212 }
213}
214
215impl<'a, T> DerefMut for Exclusive<'a, T> {
216 fn deref_mut(&mut self) -> &mut T {
217 self.0
218 }
219}
220
221impl<'a, T> Mutex for Exclusive<'a, T> {
222 type Data = T;
223
224 fn lock<R>(&mut self, f: impl FnOnce(&mut T) -> R) -> R {
225 f(self.0)
226 }
227}
228
229#[cfg(test)]
230#[allow(dead_code)]
231mod tests {
232 use crate::prelude::*;
233 use crate::Exclusive;
234
235 fn compile_test_single_move(mut a: impl Mutex<Data = i32>) {
236 a.lock(|a| {
237 *a += 1;
238 });
239 }
240
241 fn compile_test_single_reference(a: &mut impl Mutex<Data = i32>) {
242 a.lock(|a| {
243 *a += 1;
244 });
245 }
246
247 fn compile_test_double_move(mut a: impl Mutex<Data = i32>, mut b: impl Mutex<Data = i32>) {
248 a.lock(|a| {
249 *a += 1;
250 });
251
252 b.lock(|b| {
253 *b += 1;
254 });
255
256 (a, b).lock(|a, b| {
257 *a += 1;
258 *b += 1;
259 });
260 }
261
262 fn compile_test_double_reference(
263 a: &mut impl Mutex<Data = i32>,
264 b: &mut impl Mutex<Data = i32>,
265 ) {
266 a.lock(|a| {
267 *a += 1;
268 });
269
270 b.lock(|b| {
271 *b += 1;
272 });
273
274 (a, b).lock(|a, b| {
275 *a += 1;
276 *b += 1;
277 });
278 }
279
280 fn compile_test_move_and_reference(
281 mut a: impl Mutex<Data = i32>,
282 b: &mut impl Mutex<Data = i32>,
283 ) {
284 a.lock(|a| {
285 *a += 1;
286 });
287
288 b.lock(|b| {
289 *b += 1;
290 });
291
292 (a, b).lock(|a, b| {
293 *a += 1;
294 *b += 1;
295 });
296 }
297
298 #[test]
299 fn refcell_lock() {
300 let a = core::cell::RefCell::new(0);
301 let b = core::cell::RefCell::new(0);
302
303 (&a).lock(|a| {
304 *a += 1;
305 });
306
307 (&b).lock(|b| {
308 *b += 1;
309 });
310
311 (&a, &b).lock(|a, b| {
312 *a += 1;
313 *b += 1;
314 });
315 }
316
317 #[test]
318 fn exclusive() {
319 let mut var = 0;
320 let mut excl = Exclusive(&mut var);
321
322 excl.lock(|val| *val += 1);
323
324 assert_eq!(*excl.into_inner(), 1);
325 }
326}