one_shot_mutex/unsync/
mutex.rs
1use core::cell::Cell;
2
3use lock_api::{GuardSend, RawMutex, RawMutexFair};
4
5pub struct RawOneShotMutex {
36 lock: Cell<bool>,
37}
38
39impl RawOneShotMutex {
40 pub const fn new() -> Self {
41 Self::INIT
42 }
43}
44
45impl Default for RawOneShotMutex {
46 fn default() -> Self {
47 Self::new()
48 }
49}
50
51unsafe impl RawMutex for RawOneShotMutex {
52 #[allow(clippy::declare_interior_mutable_const)]
53 const INIT: Self = Self {
54 lock: Cell::new(false),
55 };
56
57 type GuardMarker = GuardSend;
58
59 #[inline]
60 fn lock(&self) {
61 assert!(
62 self.try_lock(),
63 "called `lock` on a `RawOneShotMutex` that is already locked"
64 );
65 }
66
67 #[inline]
68 fn try_lock(&self) -> bool {
69 let was_locked = self.lock.replace(true);
70 !was_locked
71 }
72
73 #[inline]
74 unsafe fn unlock(&self) {
75 self.lock.set(false);
76 }
77
78 #[inline]
79 fn is_locked(&self) -> bool {
80 self.lock.get()
81 }
82}
83
84unsafe impl RawMutexFair for RawOneShotMutex {
85 #[inline]
86 unsafe fn unlock_fair(&self) {
87 unsafe { self.unlock() }
88 }
89
90 #[inline]
91 unsafe fn bump(&self) {}
92}
93
94pub type OneShotMutex<T> = lock_api::Mutex<RawOneShotMutex, T>;
96
97pub type OneShotMutexGuard<'a, T> = lock_api::MutexGuard<'a, RawOneShotMutex, T>;
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn lock() {
106 let mutex = OneShotMutex::new(42);
107 let mut guard = mutex.lock();
108 assert_eq!(*guard, 42);
109
110 *guard += 1;
111 drop(guard);
112 let guard = mutex.lock();
113 assert_eq!(*guard, 43);
114 }
115
116 #[test]
117 #[should_panic]
118 fn lock_panic() {
119 let mutex = OneShotMutex::new(42);
120 let _guard = mutex.lock();
121 let _guard2 = mutex.lock();
122 }
123
124 #[test]
125 fn try_lock() {
126 let mutex = OneShotMutex::new(42);
127 let mut guard = mutex.try_lock().unwrap();
128 assert_eq!(*guard, 42);
129 assert!(mutex.try_lock().is_none());
130
131 *guard += 1;
132 drop(guard);
133 let guard = mutex.try_lock().unwrap();
134 assert_eq!(*guard, 43);
135 }
136}