1use realtime_core::*;
2use std::thread;
3use std::time::{Duration, Instant};
4use thread_priority::*;
5
6pub struct RtThread {
7 last_time: Instant,
8 period: Duration,
9}
10impl RtThread {
11 pub fn new(prio: u8) -> Result<Self> {
12 if prio > 0 {
13 let thread_id = thread_native_id();
14 #[cfg(not(windows))]
15 let policy = ThreadSchedulePolicy::Realtime(RealtimeThreadSchedulePolicy::Fifo);
16 let rt = if prio > 99 { 99 } else { prio };
17 let priority = ThreadPriority::Crossplatform(rt.try_into().unwrap());
18 #[cfg(not(windows))]
19 if !nix::unistd::Uid::effective().is_root() {
20 return Err(ErrorKind::NotRoot);
21 }
22 #[cfg(not(windows))]
23 let result = set_thread_priority_and_policy(thread_id, priority, policy);
24 #[cfg(windows)]
25 let result = set_thread_priority(thread_id, priority);
26 if let Err(err) = result {
27 log::warn!("failed to set_thread_priority: {:?}", err);
28 }
29 }
30
31 Ok(Self {
32 last_time: Instant::now(),
33 period: Duration::ZERO,
34 })
35 }
36}
37impl RealTime for RtThread {
38 fn start(&mut self, period: Duration) -> Result<()> {
39 self.last_time = Instant::now();
40 self.period = period;
41 Ok(())
42 }
43 fn stop(&mut self) -> Result<()> {
44 self.period = Duration::ZERO;
45 Ok(())
46 }
47 fn wait_period(&mut self) -> Result<()> {
48 if self.period == Duration::ZERO {
49 return Err(ErrorKind::NotStart);
50 };
51 let next_time = self.last_time + self.period;
52 let now = Instant::now();
53 if now < next_time {
54 let sleep = next_time - now;
55 thread::sleep(sleep);
56 }
57 self.last_time = next_time;
58 Ok(())
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn tolerance() {
68 let mut rtai = RtThread::new(90).unwrap();
69 rtai.start(Duration::from_millis(1)).unwrap();
70 rtai.wait_period().unwrap();
71 let mut last_time = clock_source::now();
72 for _ in 0..1_000 {
73 rtai.wait_period().unwrap();
74 let now = clock_source::now();
75 if now - last_time > 1_600_000 {
76 println!("{}", now - last_time - 1_000_000);
77 }
78 assert!(now - last_time < 1_600_000);
79 last_time = now;
80 }
81 }
82}