Skip to main content

kithara_platform/sync/
mutex.rs

1use std::ops::{Deref, DerefMut};
2
3#[cfg(not(target_arch = "wasm32"))]
4use parking_lot::Mutex as ParkingLotMutex;
5
6#[cfg(not(target_arch = "wasm32"))]
7pub struct Mutex<T>(ParkingLotMutex<T>);
8
9#[cfg(not(target_arch = "wasm32"))]
10impl<T> Mutex<T> {
11    #[inline]
12    pub fn new(value: T) -> Self {
13        Self(ParkingLotMutex::new(value))
14    }
15
16    #[inline]
17    pub fn lock_sync(&self) -> MutexGuard<'_, T> {
18        MutexGuard(self.0.lock())
19    }
20
21    /// Try to acquire the lock without blocking.
22    ///
23    /// # Errors
24    ///
25    /// Returns [`NotAvailable`] if the mutex is already held.
26    #[inline]
27    pub fn try_lock(&self) -> Result<MutexGuard<'_, T>, NotAvailable> {
28        self.0.try_lock().map(MutexGuard).ok_or(NotAvailable)
29    }
30}
31
32#[cfg(not(target_arch = "wasm32"))]
33impl<T: Default> Default for Mutex<T> {
34    fn default() -> Self {
35        Self::new(T::default())
36    }
37}
38
39#[cfg(not(target_arch = "wasm32"))]
40pub struct MutexGuard<'a, T>(pub(super) parking_lot::MutexGuard<'a, T>);
41
42#[cfg(not(target_arch = "wasm32"))]
43impl<T> Deref for MutexGuard<'_, T> {
44    type Target = T;
45
46    #[inline]
47    fn deref(&self) -> &T {
48        &self.0
49    }
50}
51
52#[cfg(not(target_arch = "wasm32"))]
53impl<T> DerefMut for MutexGuard<'_, T> {
54    #[inline]
55    fn deref_mut(&mut self) -> &mut T {
56        &mut self.0
57    }
58}
59
60#[cfg(target_arch = "wasm32")]
61use wasm_safe_thread::Mutex as WasmMutex;
62
63#[cfg(target_arch = "wasm32")]
64pub struct Mutex<T>(WasmMutex<T>);
65
66#[cfg(target_arch = "wasm32")]
67impl<T> Mutex<T> {
68    #[inline]
69    pub fn new(value: T) -> Self {
70        Self(WasmMutex::new(value))
71    }
72
73    #[inline]
74    pub fn lock_sync(&self) -> MutexGuard<'_, T> {
75        MutexGuard(self.0.lock_sync())
76    }
77
78    /// Try to acquire the lock without blocking.
79    ///
80    /// # Errors
81    ///
82    /// Returns [`NotAvailable`] if the mutex is already held.
83    #[inline]
84    pub fn try_lock(&self) -> Result<MutexGuard<'_, T>, NotAvailable> {
85        self.0.try_lock().map(MutexGuard).map_err(|_| NotAvailable)
86    }
87}
88
89#[cfg(target_arch = "wasm32")]
90impl<T: Default> Default for Mutex<T> {
91    fn default() -> Self {
92        Self::new(T::default())
93    }
94}
95
96#[cfg(target_arch = "wasm32")]
97pub struct MutexGuard<'a, T>(pub(super) wasm_safe_thread::guard::Guard<'a, T>);
98
99#[cfg(target_arch = "wasm32")]
100impl<T> Deref for MutexGuard<'_, T> {
101    type Target = T;
102
103    #[inline]
104    fn deref(&self) -> &T {
105        &self.0
106    }
107}
108
109#[cfg(target_arch = "wasm32")]
110impl<T> DerefMut for MutexGuard<'_, T> {
111    #[inline]
112    fn deref_mut(&mut self) -> &mut T {
113        &mut self.0
114    }
115}
116
117/// `try_lock()` failed because the mutex is already held.
118#[derive(Debug, Clone, Copy, PartialEq, Eq)]
119pub struct NotAvailable;
120
121impl std::fmt::Display for NotAvailable {
122    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123        f.write_str("mutex is already locked")
124    }
125}
126
127impl std::error::Error for NotAvailable {}