esp32_nimble/utilities/
mutex.rs1use core::cell::UnsafeCell;
4use core::ops::{Deref, DerefMut};
5use esp_idf_svc::sys::*;
6
7const PTHREAD_MUTEX_INITIALIZER: u32 = 0xFFFFFFFF;
9
10pub struct RawMutex(UnsafeCell<pthread_mutex_t>);
11
12impl RawMutex {
13 #[inline(always)]
14 pub const fn new() -> Self {
15 Self(UnsafeCell::new(PTHREAD_MUTEX_INITIALIZER as _))
16 }
17
18 #[inline(always)]
19 #[allow(clippy::missing_safety_doc)]
20 pub unsafe fn lock(&self) {
21 let r = unsafe { pthread_mutex_lock(self.0.get()) };
22 debug_assert_eq!(r, 0);
23 }
24
25 #[inline(always)]
26 #[allow(clippy::missing_safety_doc)]
27 pub unsafe fn try_lock(&self) -> bool {
28 unsafe { pthread_mutex_trylock(self.0.get()) == 0 }
29 }
30
31 #[inline(always)]
32 #[allow(clippy::missing_safety_doc)]
33 pub unsafe fn unlock(&self) {
34 let r = unsafe { pthread_mutex_unlock(self.0.get()) };
35 debug_assert_eq!(r, 0);
36 }
37}
38
39impl Drop for RawMutex {
40 fn drop(&mut self) {
41 let r = unsafe { pthread_mutex_destroy(self.0.get_mut() as *mut _) };
42 debug_assert_eq!(r, 0);
43 }
44}
45
46unsafe impl Sync for RawMutex {}
47unsafe impl Send for RawMutex {}
48
49pub struct Mutex<T>(RawMutex, UnsafeCell<T>);
50
51#[allow(dead_code)]
52impl<T> Mutex<T> {
53 #[inline(always)]
54 pub const fn new(data: T) -> Self {
55 Self(RawMutex::new(), UnsafeCell::new(data))
56 }
57
58 #[inline(always)]
59 pub fn lock(&self) -> MutexGuard<'_, T> {
60 MutexGuard::new(self)
61 }
62
63 #[inline(always)]
64 pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
65 MutexGuard::try_new(self)
66 }
67
68 #[inline(always)]
69 pub(crate) fn into_innter(self) -> T {
70 self.1.into_inner()
71 }
72
73 #[inline]
74 pub(crate) unsafe fn raw(&self) -> &'_ T {
75 unsafe { self.1.get().as_mut().unwrap() }
76 }
77}
78
79unsafe impl<T> Sync for Mutex<T> where T: Send {}
80unsafe impl<T> Send for Mutex<T> where T: Send {}
81
82pub struct MutexGuard<'a, T>(&'a Mutex<T>);
83
84impl<'a, T> MutexGuard<'a, T> {
85 #[inline(always)]
86 fn new(mutex: &'a Mutex<T>) -> Self {
87 unsafe {
88 mutex.0.lock();
89 }
90
91 Self(mutex)
92 }
93
94 #[inline(always)]
95 fn try_new(mutex: &'a Mutex<T>) -> Option<Self> {
96 if unsafe { mutex.0.try_lock() } {
97 Some(Self(mutex))
98 } else {
99 None
100 }
101 }
102}
103
104impl<T> Drop for MutexGuard<'_, T> {
105 #[inline(always)]
106 fn drop(&mut self) {
107 unsafe {
108 self.0.0.unlock();
109 }
110 }
111}
112
113impl<T> Deref for MutexGuard<'_, T> {
114 type Target = T;
115
116 #[inline(always)]
117 fn deref(&self) -> &Self::Target {
118 unsafe { self.0.1.get().as_mut().unwrap() }
119 }
120}
121
122impl<T> DerefMut for MutexGuard<'_, T> {
123 #[inline(always)]
124 fn deref_mut(&mut self) -> &mut Self::Target {
125 unsafe { self.0.1.get().as_mut().unwrap() }
126 }
127}