esp32_nimble/utilities/
mutex.rs

1// original: https://github.com/esp-rs/esp-idf-svc/blob/master/src/private/mutex.rs
2
3use core::cell::UnsafeCell;
4use core::ops::{Deref, DerefMut};
5use esp_idf_svc::sys::*;
6
7// NOTE: ESP-IDF-specific
8const 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}