stm32f1_hal/common/
atomic_mutex.rs1use core::{
2 cell::UnsafeCell,
3 fmt::{self, Debug, Formatter},
4 ops::{Deref, DerefMut},
5 sync::atomic::*,
6};
7
8pub struct AtomicMutex<T> {
12 data: UnsafeCell<T>,
13 state: AtomicBool,
14}
15
16unsafe impl<T> Send for AtomicMutex<T> {}
17unsafe impl<T> Sync for AtomicMutex<T> {}
18
19impl<T> Debug for AtomicMutex<T> {
20 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
21 f.write_str(match self.state.load(Ordering::Relaxed) {
22 true => "Locked",
23 _ => "Unlocked",
24 })
25 }
26}
27
28impl<T> AtomicMutex<T> {
29 pub const fn new(value: T) -> Self {
31 Self {
32 data: UnsafeCell::new(value),
33 state: AtomicBool::new(false),
34 }
35 }
36
37 pub fn try_lock(&self) -> Option<AtomicMutexGuard<'_, T>> {
39 if self
40 .state
41 .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
42 .is_ok()
43 {
44 Some(AtomicMutexGuard { m: self })
45 } else {
46 None
47 }
48 }
49
50 #[allow(clippy::mut_from_ref)]
51 #[inline]
52 fn get_data_mut(&self) -> &mut T {
53 unsafe { &mut *self.data.get() }
54 }
55}
56
57#[derive(Debug)]
61pub struct AtomicMutexGuard<'mutex, T> {
62 m: &'mutex AtomicMutex<T>,
63}
64
65impl<'mutex, T> Deref for AtomicMutexGuard<'mutex, T> {
66 type Target = T;
67
68 fn deref(&self) -> &T {
69 self.m.get_data_mut()
70 }
71}
72
73impl<'mutex, T> DerefMut for AtomicMutexGuard<'mutex, T> {
74 fn deref_mut(&mut self) -> &mut T {
75 self.m.get_data_mut()
76 }
77}
78
79impl<'mutex, T> Drop for AtomicMutexGuard<'mutex, T> {
80 fn drop(&mut self) {
81 self.m.state.store(false, Ordering::Release);
82 }
83}
84
85#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[derive(Debug, PartialEq)]
92 struct TestData {
93 a: u8,
94 b: u8,
95 }
96
97 #[test]
98 fn lock() {
99 let l = AtomicMutex::<TestData>::new(TestData { a: 1, b: 2 });
100 {
101 let mut d = l.try_lock().unwrap();
102 assert_eq!(d.a, 1);
103 assert_eq!(d.b, 2);
104 let d2 = l.try_lock();
105 assert!(d2.is_none());
106 d.a += 1;
107 }
108 }
109}