os_trait/
notifier.rs

1use timeout_trait::TimeoutState;
2
3use crate::{OsInterface, TimeoutNs, fugit::MicrosDurationU32};
4
5/// This method should be able to call from task or ISR.
6/// The implementation should handle the different situations.
7pub trait Notifier: Send + Clone {
8    fn notify(&self) -> bool;
9}
10
11pub trait NotifyWaiter: Send {
12    /// Wait until notified or timeout occurs.
13    /// # Returns
14    ///   - `true` notified
15    ///   - `false` timeout occurred
16    fn wait(&self, timeout: MicrosDurationU32) -> bool;
17
18    /// # Description
19    /// Wait for a notification, but it can split the total timeout into small timeout.
20    /// Your function will be called once immediately and after each small timeout.
21    /// It's useful when you want to check something while it's waiting.
22    ///
23    /// # Parameters
24    /// - `timeout`: Total timeout.
25    /// - `count`: How many times to split the total timeout.
26    ///   If you’re not sure, set it to `1`. Do **NOT** set it to `0`.
27    /// - `f`: Your function. If it returns `Some()`, it will break out of the wait.
28    ///
29    /// # Returns
30    /// - `None`: It's timeout.
31    /// - `Some(x)`: The value returned by your function.
32    ///
33    /// # Note
34    /// It may call your function more times than expected and wait longer than expected.
35    #[inline]
36    fn wait_with<OS: OsInterface, U>(
37        &self,
38        _os: OS,
39        timeout: MicrosDurationU32,
40        count: u32,
41        mut f: impl FnMut() -> Option<U>,
42    ) -> Option<U> {
43        assert!(count > 0);
44        let wait_t = MicrosDurationU32::from_ticks(timeout.ticks() / count);
45        let mut t = OS::timeout().start_us(timeout.ticks());
46        loop {
47            if let Some(rst) = f() {
48                return Some(rst);
49            } else if t.timeout() {
50                return None;
51            }
52            self.wait(wait_t);
53        }
54    }
55}