1 | #[cfg (not(feature = "std" ))] |
2 | pub use no_std_lock::*; |
3 | #[cfg (feature = "std" )] |
4 | pub use std_lock::*; |
5 | |
6 | #[cfg (feature = "std" )] |
7 | mod std_lock { |
8 | use std::sync::Mutex as StdMutex; |
9 | pub use std::sync::MutexGuard; |
10 | |
11 | /// A wrapper around [`std::sync::Mutex`]. |
12 | #[derive (Debug)] |
13 | pub struct Mutex<T> { |
14 | inner: StdMutex<T>, |
15 | } |
16 | |
17 | impl<T> Mutex<T> { |
18 | /// Creates a new mutex in an unlocked state ready for use. |
19 | pub fn new(data: T) -> Self { |
20 | Self { |
21 | inner: StdMutex::new(data), |
22 | } |
23 | } |
24 | |
25 | /// Acquires the mutex, blocking the current thread until it is able to do so. |
26 | /// |
27 | /// This will return `None` in the case the mutex is poisoned. |
28 | #[inline ] |
29 | pub fn lock(&self) -> Option<MutexGuard<'_, T>> { |
30 | self.inner.lock().ok() |
31 | } |
32 | } |
33 | } |
34 | |
35 | #[cfg (not(feature = "std" ))] |
36 | mod no_std_lock { |
37 | use alloc::boxed::Box; |
38 | use core::fmt::Debug; |
39 | use core::ops::DerefMut; |
40 | |
41 | use crate::sync::Arc; |
42 | |
43 | /// A no-std compatible wrapper around [`Lock`]. |
44 | #[derive (Debug)] |
45 | pub struct Mutex<T> { |
46 | inner: Arc<dyn Lock<T>>, |
47 | } |
48 | |
49 | impl<T: Send + 'static> Mutex<T> { |
50 | /// Creates a new mutex in an unlocked state ready for use. |
51 | pub fn new<M>(val: T) -> Self |
52 | where |
53 | M: MakeMutex, |
54 | T: Send + 'static, |
55 | { |
56 | Self { |
57 | inner: M::make_mutex(val), |
58 | } |
59 | } |
60 | |
61 | /// Acquires the mutex, blocking the current thread until it is able to do so. |
62 | /// |
63 | /// This will return `None` in the case the mutex is poisoned. |
64 | #[inline ] |
65 | pub fn lock(&self) -> Option<MutexGuard<'_, T>> { |
66 | self.inner.lock().ok() |
67 | } |
68 | } |
69 | |
70 | /// A lock protecting shared data. |
71 | pub trait Lock<T>: Debug + Send + Sync { |
72 | /// Acquire the lock. |
73 | fn lock(&self) -> Result<MutexGuard<'_, T>, Poisoned>; |
74 | } |
75 | |
76 | /// A lock builder. |
77 | pub trait MakeMutex { |
78 | /// Create a new mutex. |
79 | fn make_mutex<T>(value: T) -> Arc<dyn Lock<T>> |
80 | where |
81 | T: Send + 'static; |
82 | } |
83 | |
84 | /// A no-std compatible mutex guard. |
85 | pub type MutexGuard<'a, T> = Box<dyn DerefMut<Target = T> + 'a>; |
86 | |
87 | /// A marker type used to indicate `Lock::lock` failed due to a poisoned lock. |
88 | pub struct Poisoned; |
89 | } |
90 | |