1use core::{
2 fmt::{self, Debug, Formatter},
3 ops::{Deref, DerefMut},
4};
5
6#[cfg(feature = "alloc")]
7use alloc::sync::Arc;
8
9use super::{
10 error::{MutexLockError, OptionLockError, PoisonError},
11 lock::{OptionGuard, OptionLock},
12};
13
14#[cfg(feature = "alloc")]
15use super::arc::MutexGuardArc;
16
17#[repr(transparent)]
19pub struct Mutex<T> {
20 pub(crate) inner: OptionLock<T>,
21}
22
23impl<T> Mutex<T> {
24 pub const fn new(value: T) -> Self {
26 Self {
27 inner: OptionLock::new(value),
28 }
29 }
30
31 #[inline]
32 pub(crate) unsafe fn as_ptr(&self) -> *const T {
33 self.inner.as_ptr()
34 }
35
36 #[inline]
37 pub(crate) unsafe fn as_mut_ptr(&self) -> *mut T {
38 self.inner.as_mut_ptr()
39 }
40
41 #[inline]
43 pub fn is_locked(&self) -> bool {
44 self.inner.is_locked()
45 }
46
47 #[inline]
49 pub fn is_poisoned(&self) -> bool {
50 !self.inner.is_some()
51 }
52
53 pub fn get_mut(&mut self) -> &mut T {
55 unsafe { &mut *self.as_mut_ptr() }
56 }
57
58 pub fn into_inner(self) -> Result<T, PoisonError> {
60 self.inner.into_inner().ok_or(PoisonError)
61 }
62
63 #[inline]
65 pub fn try_lock(&self) -> Result<MutexGuard<'_, T>, MutexLockError> {
66 match self.inner.try_get() {
67 Ok(guard) => Ok(guard),
68 Err(OptionLockError::FillState) => Err(MutexLockError::Poisoned),
69 Err(OptionLockError::Unavailable) => Err(MutexLockError::Unavailable),
70 }
71 }
72
73 #[cfg(feature = "alloc")]
74 pub fn try_lock_arc(self: &Arc<Self>) -> Result<MutexGuardArc<T>, MutexLockError> {
76 self.try_lock()
77 .map(|guard| MutexGuardArc::new(self.clone(), guard))
78 }
79
80 pub fn spin_lock(&self) -> Result<MutexGuard<'_, T>, PoisonError> {
82 let guard = self.inner.spin_lock();
83 if guard.is_none() {
84 Err(PoisonError)
85 } else {
86 Ok(MutexGuard::new(guard))
87 }
88 }
89}
90
91impl<T: Clone> Mutex<T> {
92 #[inline]
94 pub fn try_clone(&self) -> Result<T, MutexLockError> {
95 self.try_lock().map(|g| (*g).clone())
96 }
97}
98
99impl<T: Copy> Mutex<T> {
100 #[inline]
105 pub fn try_copy(&self) -> Result<T, MutexLockError> {
106 self.try_lock().map(|g| *g)
107 }
108}
109
110impl<T> Debug for Mutex<T> {
111 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
112 write!(f, "Mutex({:?})", &self.inner.state)
113 }
114}
115
116#[cfg(feature = "std")]
117impl<T> ::std::panic::RefUnwindSafe for Mutex<T> {}
118#[cfg(feature = "std")]
119impl<T> ::std::panic::UnwindSafe for Mutex<T> {}
120
121pub struct MutexGuard<'a, T>(OptionGuard<'a, T>);
123
124impl<'a, T> MutexGuard<'a, T> {
125 #[inline]
126 pub(crate) fn new(guard: OptionGuard<'a, T>) -> Self {
127 Self(guard)
128 }
129}
130
131impl<T> MutexGuard<'_, T> {
132 pub fn extract(mut slf: Self) -> T {
135 slf.0.take().unwrap()
136 }
137
138 pub fn replace(slf: &mut Self, value: T) -> T {
140 slf.0.replace(value).unwrap()
141 }
142}
143
144impl<T> Deref for MutexGuard<'_, T> {
145 type Target = T;
146
147 fn deref(&self) -> &Self::Target {
148 self.0.as_ref().unwrap()
149 }
150}
151
152impl<T> DerefMut for MutexGuard<'_, T> {
153 fn deref_mut(&mut self) -> &mut Self::Target {
154 self.0.as_mut().unwrap()
155 }
156}
157
158impl<T: Debug> Debug for MutexGuard<'_, T> {
159 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
160 f.debug_tuple("MutexGuard").field(&**self).finish()
161 }
162}
163
164#[cfg(feature = "std")]
165impl<T> Drop for MutexGuard<'_, T> {
166 fn drop(&mut self) {
167 if self.0.is_some() && ::std::thread::panicking() {
170 self.0.take();
171 }
172 }
173}
174
175unsafe impl<T: Send> Send for MutexGuard<'_, T> {}
176unsafe impl<T: Sync> Sync for MutexGuard<'_, T> {}