no_std_async/
mutex.rs

1use crate::semaphore::Semaphore;
2use core::{
3    cell::UnsafeCell,
4    ops::{Deref, DerefMut},
5};
6
7/// An async mutex.
8/// This is similar to the [`Mutex`] type in the standard library, but it is async.
9///
10/// This type only implements [`Sync`] when `T` is [`Send`]. Values are provided through the [`Deref`]
11/// and [`DerefMut`] implementations on the [`Guard`] type.
12///
13/// # Examples
14/// ```rust
15/// use no_std_async::Mutex;
16/// # fn main() { std::thread::spawn(|| pollster::block_on(task_1())); pollster::block_on(task_2()); }
17///
18/// static COUNT: Mutex<u8> = Mutex::new(0);
19///
20/// // These functions will each trade the lock, counting it up to infinity (in this case, u8::MAX).
21///
22/// async fn task_1() {
23///     loop {
24///         let mut count = COUNT.lock().await;
25///         if *count == u8::MAX {
26///             break;
27///         }
28///         let expected = *count + 1;
29///         *count += 1;
30///         assert_eq!(expected, *count); // we have the lock, so our value can't be modified otherwise.
31///     }
32/// }
33///
34/// async fn task_2() {
35///    loop {
36///       let mut count = COUNT.lock().await;
37///       if *count == u8::MAX {
38///           break;
39///       }
40///       let expected = *count + 1;
41///       *count += 1;
42///       assert_eq!(expected, *count); // we have the lock, so our value can't be modified otherwise.
43///   }
44/// }
45///
46pub struct Mutex<T> {
47    data: UnsafeCell<T>,
48    semaphore: Semaphore,
49}
50impl<T> Mutex<T> {
51    /// Creates a new [`Mutex`] with the given data.
52    pub const fn new(data: T) -> Self {
53        Self {
54            data: UnsafeCell::new(data),
55            semaphore: Semaphore::new(1),
56        }
57    }
58
59    /// Acquires a lock on the data.
60    pub async fn lock<'a>(&'a self) -> Guard<'a, T>
61    where
62        T: 'a,
63    {
64        self.semaphore.acquire(1).await;
65        Guard { mutex: self }
66    }
67}
68
69unsafe impl<T: Send> Send for Mutex<T> {}
70unsafe impl<T: Send> Sync for Mutex<T> {}
71
72/// A guard that provides mutable access to the data inside of a [`Mutex`].
73/// The data can be accessed using the [`Deref`] and [`DerefMut`] implementations.
74pub struct Guard<'a, T> {
75    mutex: &'a Mutex<T>,
76}
77impl<T> Deref for Guard<'_, T> {
78    type Target = T;
79
80    fn deref(&self) -> &Self::Target {
81        unsafe { &*self.mutex.data.get() }
82    }
83}
84impl<T> DerefMut for Guard<'_, T> {
85    fn deref_mut(&mut self) -> &mut Self::Target {
86        unsafe { &mut *self.mutex.data.get() }
87    }
88}
89impl<T> Drop for Guard<'_, T> {
90    fn drop(&mut self) {
91        self.mutex.semaphore.release(1);
92    }
93}