1#![no_std]
5
6use core::cell::UnsafeCell;
7use core::convert::From;
8use core::fmt;
9use core::fmt::{Debug, Display};
10use core::marker::PhantomData;
11use core::ops::{Deref, DerefMut};
12use core::panic::{RefUnwindSafe, UnwindSafe};
13use core::sync::atomic::{AtomicBool, Ordering};
14
15pub struct TryMutex<T> {
18 data: UnsafeCell<T>,
19 locked: AtomicBool,
20}
21
22impl<T> TryMutex<T> {
23 #[inline]
25 pub const fn new(t: T) -> Self {
26 TryMutex {
27 data: UnsafeCell::new(t),
28 locked: AtomicBool::new(false),
29 }
30 }
31
32 #[inline]
36 pub fn try_lock(&self) -> Option<TryMutexGuard<'_, T>> {
37 self.locked
38 .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
39 .ok()
40 .map(|_| TryMutexGuard {
41 lock: self,
42 notsend: PhantomData,
43 })
44 }
45
46 #[inline]
48 pub fn into_inner(self) -> T {
49 self.data.into_inner()
50 }
51
52 #[inline]
55 pub fn get_mut(&mut self) -> &mut T {
56 unsafe { &mut *self.data.get() }
57 }
58}
59
60impl<T: Default> Default for TryMutex<T> {
61 fn default() -> Self {
62 Self::new(T::default())
63 }
64}
65
66impl<T: Debug> Debug for TryMutex<T> {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 if let Some(guard) = self.try_lock() {
69 f.debug_struct("TryMutex").field("data", &*guard).finish()
70 } else {
71 struct LockedPlaceholder;
72 impl fmt::Debug for LockedPlaceholder {
73 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74 f.write_str("<locked>")
75 }
76 }
77
78 f.debug_struct("TryMutex")
79 .field("data", &LockedPlaceholder)
80 .finish()
81 }
82 }
83}
84
85pub struct TryMutexGuard<'a, T: 'a> {
88 lock: &'a TryMutex<T>,
89 notsend: PhantomData<*mut T>,
90}
91
92impl<'a, T> Deref for TryMutexGuard<'a, T> {
93 type Target = T;
94
95 fn deref(&self) -> &T {
96 unsafe { &*self.lock.data.get() }
97 }
98}
99
100impl<'a, T> DerefMut for TryMutexGuard<'a, T> {
101 fn deref_mut(&mut self) -> &mut T {
102 unsafe { &mut *self.lock.data.get() }
103 }
104}
105
106impl<'a, T> Drop for TryMutexGuard<'a, T> {
107 fn drop(&mut self) {
108 self.lock.locked.store(false, Ordering::Release);
109 }
110}
111
112impl<'a, T: Debug> Debug for TryMutexGuard<'a, T> {
113 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
114 f.debug_struct("TryMutexGuard")
115 .field("data", &**self)
116 .finish()
117 }
118}
119
120impl<'a, T: Display> Display for TryMutexGuard<'a, T> {
121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122 (**self).fmt(f)
123 }
124}
125
126impl<T> UnwindSafe for TryMutex<T> {}
127impl<T> RefUnwindSafe for TryMutex<T> {}
128unsafe impl<T: Send> Send for TryMutex<T> {}
129unsafe impl<T: Send> Sync for TryMutex<T> {}
130unsafe impl<'a, T: Sync> Sync for TryMutexGuard<'a, T> {}
131unsafe impl<'a, T: Send> Send for TryMutexGuard<'a, T> {}
132
133impl<T> From<T> for TryMutex<T> {
134 fn from(t: T) -> Self {
135 TryMutex::new(t)
136 }
137}