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}