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}