os_trait/
os_impls.rs

1use crate::{
2    mutex_impls::*,
3    notifier_impls::*,
4    prelude::*,
5    timeout_trait::{delay_impls::*, fake_impls::*},
6};
7cfg_if::cfg_if! {
8    if #[cfg(feature = "std")] {
9        use std::thread;
10        use crate::timeout_trait::std_impls::*;
11    }
12}
13
14// STD --------------------------------------------------------------
15
16/// This implementation is only for unit testing.
17pub struct StdOs;
18#[cfg(feature = "std")]
19impl OsInterface for StdOs {
20    type RawMutex = FakeRawMutex;
21    type Notifier = StdNotifier;
22    type NotifyWaiter = StdNotifyWaiter;
23    type Timeout = StdTimeoutNs;
24    type TimeoutState = StdTimeoutState;
25    type Delay = StdDelayNs;
26
27    const O: Self = Self {};
28
29    #[inline]
30    fn yield_thread() {
31        thread::yield_now();
32    }
33
34    #[inline]
35    fn timeout() -> Self::Timeout {
36        StdTimeoutNs {}
37    }
38
39    #[inline]
40    fn delay() -> Self::Delay {
41        StdDelayNs {}
42    }
43
44    #[inline]
45    fn notify() -> (Self::Notifier, Self::NotifyWaiter) {
46        StdNotifier::new()
47    }
48}
49
50// Fake -------------------------------------------------------------
51
52pub struct FakeOs;
53impl OsInterface for FakeOs {
54    type RawMutex = FakeRawMutex;
55    type Notifier = FakeNotifier;
56    type NotifyWaiter = FakeNotifier;
57    type Timeout = FakeTimeoutNs;
58    type TimeoutState = FakeTimeoutState;
59    type Delay = TickDelay<FakeInstant>;
60
61    const O: Self = Self {};
62
63    #[inline]
64    fn yield_thread() {}
65
66    #[inline]
67    fn timeout() -> Self::Timeout {
68        FakeTimeoutNs::new()
69    }
70
71    #[inline]
72    fn delay() -> Self::Delay {
73        TickDelay::<FakeInstant>::default()
74    }
75
76    #[inline]
77    fn notify() -> (Self::Notifier, Self::NotifyWaiter) {
78        FakeNotifier::new()
79    }
80}
81
82// Tests ------------------------------------------------------------
83
84#[cfg(feature = "std")]
85#[cfg(test)]
86mod tests {
87    use super::*;
88    use crate::fugit::ExtU32;
89
90    struct OsUser<OS: OsInterface> {
91        notifier: OS::Notifier,
92        waiter: OS::NotifyWaiter,
93        mutex: Mutex<OS, u8>,
94        interval: OS::TimeoutState,
95    }
96
97    impl<OS: OsInterface> OsUser<OS> {
98        fn new() -> Self {
99            let (notifier, waiter) = OS::notify();
100            Self {
101                notifier,
102                waiter,
103                mutex: OS::mutex(1),
104                interval: OS::timeout().start_ms(1),
105            }
106        }
107
108        fn use_os(&mut self) {
109            let mutex = OS::mutex(0);
110
111            let mut guard = mutex.try_lock().unwrap();
112            assert_eq!(*guard, 0);
113            *guard = 4;
114            drop(guard);
115
116            mutex
117                .try_with_lock(|data| {
118                    assert_eq!(*data, 4);
119                    *data = 5;
120                })
121                .unwrap();
122
123            OS::yield_thread();
124            OS::delay().delay_ms(1);
125
126            let _os = OS::O;
127
128            assert!(self.notifier.notify());
129            assert!(self.waiter.wait(1.millis()));
130
131            let mut d = self.mutex.lock();
132            *d = 2;
133
134            self.interval.timeout();
135        }
136    }
137
138    #[test]
139    fn select_os() {
140        let mut user = OsUser::<FakeOs>::new();
141        user.use_os();
142        let mut user = OsUser::<StdOs>::new();
143        user.use_os();
144    }
145}