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 DelayNs = StdDelayNs;
26
27    const O: Self = Self {};
28
29    #[inline]
30    fn yield_thread() {
31        thread::yield_now();
32    }
33
34    #[inline]
35    fn delay() -> Self::DelayNs {
36        StdDelayNs {}
37    }
38
39    #[inline]
40    fn notify() -> (Self::Notifier, Self::NotifyWaiter) {
41        StdNotifier::new()
42    }
43}
44
45// Fake -------------------------------------------------------------
46
47pub struct FakeOs;
48impl OsInterface for FakeOs {
49    type RawMutex = FakeRawMutex;
50    type Notifier = FakeNotifier;
51    type NotifyWaiter = FakeNotifier;
52    type Timeout = FakeTimeoutNs;
53    type TimeoutState = FakeTimeoutState;
54    type DelayNs = TickDelay<FakeInstant>;
55
56    const O: Self = Self {};
57
58    #[inline]
59    fn yield_thread() {}
60
61    #[inline]
62    fn delay() -> Self::DelayNs {
63        TickDelay::<FakeInstant>::default()
64    }
65
66    #[inline]
67    fn notify() -> (Self::Notifier, Self::NotifyWaiter) {
68        FakeNotifier::new()
69    }
70}
71
72// Tests ------------------------------------------------------------
73
74#[cfg(feature = "std")]
75#[cfg(test)]
76mod tests {
77    use super::*;
78    use crate::fugit::ExtU32;
79
80    struct OsUser<OS: OsInterface> {
81        notifier: OS::Notifier,
82        waiter: OS::NotifyWaiter,
83        mutex: Mutex<OS, u8>,
84        interval: OS::TimeoutState,
85    }
86
87    impl<OS: OsInterface> OsUser<OS> {
88        fn new() -> Self {
89            let (notifier, waiter) = OS::notify();
90            Self {
91                notifier,
92                waiter,
93                mutex: OS::mutex(1),
94                interval: OS::Timeout::start_ms(1),
95            }
96        }
97
98        fn use_os(&mut self) {
99            let mutex = OS::mutex(0);
100
101            let mut guard = mutex.try_lock().unwrap();
102            assert_eq!(*guard, 0);
103            *guard = 4;
104            drop(guard);
105
106            mutex
107                .try_with_lock(|data| {
108                    assert_eq!(*data, 4);
109                    *data = 5;
110                })
111                .unwrap();
112
113            OS::yield_thread();
114            OS::delay().delay_ms(1);
115
116            let _os = OS::O;
117
118            assert!(self.notifier.notify());
119            assert!(self.waiter.wait(1.millis()));
120
121            let mut d = self.mutex.lock();
122            *d = 2;
123
124            self.interval.timeout();
125        }
126    }
127
128    #[test]
129    fn select_os() {
130        let mut user = OsUser::<FakeOs>::new();
131        user.use_os();
132        let mut user = OsUser::<StdOs>::new();
133        user.use_os();
134    }
135}