emerald_std/sync/spin/
mutex.rs

1use core::{
2    cell::UnsafeCell,
3    fmt,
4    marker::PhantomData,
5    ops::{Deref, DerefMut},
6};
7
8use super::lock;
9
10pub struct Mutex<T: ?Sized> {
11    lock: lock::Lock,
12    data: UnsafeCell<T>,
13}
14
15unsafe impl<T: ?Sized + Send> Send for Mutex<T> {}
16unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
17
18impl<T> fmt::Debug for Mutex<T>
19where
20    T: fmt::Debug,
21{
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        let mut s = f.debug_struct("Mutex");
24        if let Some(data) = self.try_lock() {
25            s.field("data", &data);
26        } else {
27            s.field("data", &"[locked]");
28        }
29        s.finish()
30    }
31}
32
33#[must_use]
34pub struct MutexGuard<'a, T: ?Sized> {
35    lock: &'a Mutex<T>,
36    marker: PhantomData<*const ()>, // !Send
37}
38
39unsafe impl<T: ?Sized + Sync> Sync for MutexGuard<'_, T> {}
40
41impl<T> fmt::Debug for MutexGuard<'_, T>
42where
43    T: fmt::Debug,
44{
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        self.deref().fmt(f)
47    }
48}
49
50impl<T> Mutex<T> {
51    pub const fn new(data: T) -> Self {
52        Self {
53            lock: lock::Lock::new(),
54            data: UnsafeCell::new(data),
55        }
56    }
57
58    pub fn lock(&self) -> MutexGuard<'_, T> {
59        // SAFETY: we are the only accessor, and we are locking it, its never locked again until unlocked
60        self.lock.lock();
61        MutexGuard {
62            lock: self,
63            marker: PhantomData,
64        }
65    }
66
67    pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
68        if self.lock.try_lock() {
69            Some(MutexGuard {
70                lock: self,
71                marker: PhantomData,
72            })
73        } else {
74            None
75        }
76    }
77}
78
79impl<T> Deref for MutexGuard<'_, T> {
80    type Target = T;
81
82    fn deref(&self) -> &Self::Target {
83        // SAFETY: the mutex is locked, we are the only accessors,
84        //         and the pointer is valid, since it was generated for a valid T
85        unsafe { self.lock.data.get().as_ref().unwrap() }
86    }
87}
88
89impl<T> DerefMut for MutexGuard<'_, T> {
90    fn deref_mut(&mut self) -> &mut Self::Target {
91        // SAFETY: the mutex is locked, we are the only accessors,
92        //         and the pointer is valid, since it was generated for a valid T
93        unsafe { self.lock.data.get().as_mut().unwrap() }
94    }
95}
96
97impl<T: ?Sized> Drop for MutexGuard<'_, T> {
98    fn drop(&mut self) {
99        // SAFETY: the mutex is locked, we are the only accessor
100        unsafe { self.lock.lock.unlock() };
101    }
102}