os_trait/
mutex_impls.rs

1use crate::{
2    OsInterface,
3    mutex_traits::{ConstInit, RawMutex},
4};
5cfg_if::cfg_if! {
6    if #[cfg(all(feature = "std", not(feature = "std-custom-mutex")))] {
7        pub use std_impl::BlockingMutex;
8    } else {
9        pub use mutex::BlockingMutex;
10    }
11}
12
13pub type Mutex<OS, T> = BlockingMutex<<OS as OsInterface>::RawMutex, T>;
14
15/// A fake mutex is for testing.
16/// It does not provide any synchronization between threads,
17#[derive(Default)]
18pub struct FakeRawMutex {}
19
20impl FakeRawMutex {
21    /// Create a new `FakeRawMutex`.
22    pub const fn new() -> Self {
23        Self {}
24    }
25}
26
27unsafe impl Send for FakeRawMutex {}
28
29impl ConstInit for FakeRawMutex {
30    const INIT: Self = Self::new();
31}
32
33unsafe impl RawMutex for FakeRawMutex {
34    type GuardMarker = *mut ();
35
36    #[inline]
37    fn lock(&self) {}
38
39    #[inline]
40    fn try_lock(&self) -> bool {
41        true
42    }
43
44    #[inline]
45    unsafe fn unlock(&self) {}
46
47    #[inline]
48    fn is_locked(&self) -> bool {
49        true
50    }
51}
52
53#[cfg(feature = "std")]
54#[allow(dead_code)]
55mod std_impl {
56    use core::marker::PhantomData;
57    use mutex_traits::RawMutex;
58    use std::sync::MutexGuard;
59
60    /// A wrap of [`std::sync::Mutex`]. This type's purpose is to allow choosing
61    /// between using [`std::sync::Mutex`] or `BlockingMutex` through feature flags.
62    pub struct BlockingMutex<R: RawMutex, T> {
63        mutex: std::sync::Mutex<T>,
64        _marker: PhantomData<R>,
65    }
66
67    impl<R: RawMutex, T> BlockingMutex<R, T> {
68        /// Creates a new `Mutex`.
69        #[inline]
70        pub const fn new(val: T) -> BlockingMutex<R, T> {
71            Self {
72                mutex: std::sync::Mutex::new(val),
73                _marker: PhantomData,
74            }
75        }
76
77        /// lock
78        #[inline]
79        pub fn lock(&self) -> MutexGuard<'_, T> {
80            self.mutex.lock().unwrap()
81        }
82
83        /// try_lock
84        #[inline]
85        pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
86            self.mutex.try_lock().ok()
87        }
88
89        /// try_with_lock
90        #[must_use]
91        #[inline]
92        pub fn with_lock<U>(&self, f: impl FnOnce(&mut T) -> U) -> U {
93            let mut guard = self.mutex.lock().unwrap();
94            f(&mut *guard)
95        }
96
97        /// try_with_lock
98        #[must_use]
99        #[inline]
100        pub fn try_with_lock<U>(&self, f: impl FnOnce(&mut T) -> U) -> Option<U> {
101            let mut guard = self.try_lock()?;
102            Some(f(&mut *guard))
103        }
104    }
105}