lock_free_static/
mutex.rs1use core::{
2 cell::UnsafeCell,
3 mem::ManuallyDrop,
4 ops::{Deref, DerefMut},
5 panic::{RefUnwindSafe, UnwindSafe},
6 sync::atomic::{AtomicBool, Ordering},
7};
8
9pub struct Mutex<T: ?Sized> {
13 locked: AtomicBool,
14 inner: UnsafeCell<T>,
15}
16
17unsafe impl<T: Send + ?Sized> Send for Mutex<T> {}
18unsafe impl<T: Send + ?Sized> Sync for Mutex<T> {}
19
20impl<T: ?Sized> UnwindSafe for Mutex<T> {}
21impl<T: ?Sized> RefUnwindSafe for Mutex<T> {}
22
23impl<T> Mutex<T> {
24 pub const fn new(item: T) -> Self {
26 Self {
27 inner: UnsafeCell::new(item),
28 locked: AtomicBool::new(false),
29 }
30 }
31
32 pub fn into_inner(self) -> T {
34 debug_assert!(!self.locked.load(Ordering::Acquire));
35 self.inner.into_inner()
36 }
37}
38
39impl<T: Default> Default for Mutex<T> {
40 fn default() -> Self {
41 Self::new(T::default())
42 }
43}
44
45impl<T: ?Sized> Mutex<T> {
46 pub fn get_ptr(&self) -> *mut T {
48 self.inner.get()
49 }
50
51 pub fn get_mut(&mut self) -> &mut T {
53 debug_assert!(!self.locked.load(Ordering::Acquire));
54 self.inner.get_mut()
55 }
56
57 pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
62 if self.locked.swap(true, Ordering::AcqRel) {
63 None
64 } else {
65 Some(MutexGuard { owner: self })
66 }
67 }
68}
69
70pub struct MutexGuard<'a, T: ?Sized> {
74 owner: &'a Mutex<T>,
75}
76
77unsafe impl<'a, T: Sync + ?Sized> Send for MutexGuard<'a, T> {}
78unsafe impl<'a, T: Sync + ?Sized> Sync for MutexGuard<'a, T> {}
79
80impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> {
81 type Target = T;
82 fn deref(&self) -> &Self::Target {
83 unsafe { &*self.owner.get_ptr() }
84 }
85}
86impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> {
87 fn deref_mut(&mut self) -> &mut Self::Target {
88 unsafe { &mut *self.owner.get_ptr() }
89 }
90}
91
92impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
93 fn drop(&mut self) {
94 self.owner.locked.store(false, Ordering::Release);
95 }
96}
97
98impl<'a, T: ?Sized> MutexGuard<'a, T> {
99 pub fn leak(self) -> &'a mut T {
103 let this = ManuallyDrop::new(self);
104 unsafe { &mut *this.owner.get_ptr() }
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::Mutex;
111
112 #[test]
113 fn try_lock() {
114 let mutex = Mutex::<i32>::new(123);
115
116 let mut guard = mutex.try_lock().unwrap();
117 assert_eq!(*guard, 123);
118 assert!(mutex.try_lock().is_none());
119 *guard = 321;
120 assert_eq!(*guard, 321);
121 drop(guard);
122
123 assert_eq!(*mutex.try_lock().unwrap(), 321);
124 }
125
126 #[test]
127 fn leak() {
128 let mutex = Mutex::<i32>::new(123);
129 let value_mut = mutex.try_lock().unwrap().leak();
130 assert_eq!(*value_mut, 123);
131 assert!(mutex.try_lock().is_none());
132 *value_mut = 321;
133 assert_eq!(*value_mut, 321);
134 }
135}