1use crate::NativeTimerWrapper;
15
16#[cfg(target_os = "windows")]
17use winapi::shared::basetsd::DWORD_PTR;
18
19#[cfg(target_os = "linux")]
20use libc::{c_int, c_void, siginfo_t};
21
22#[cfg(target_os = "macos")]
23use libc::c_void;
24
25pub struct Timer {
26 native_timer: NativeTimerWrapper,
27 cb: Option<Box<dyn FnMut() + Send>>,
28}
29
30impl Timer {
31 pub fn new() -> Self {
32 Self {
33 native_timer: NativeTimerWrapper::new(),
34 cb: None,
35 }
36 }
37
38 pub fn start<F>(&mut self, cb: F, period_ns: u32)
39 where
40 F: 'static + FnMut() + Send,
41 {
42 self.cb = Some(Box::new(cb));
43 let ptr = self as *mut Self;
44 self.native_timer
45 .start(Some(Self::rt_thread), period_ns, ptr);
46 }
47
48 pub fn close(&mut self) {
49 self.native_timer.close();
50 }
51
52 #[cfg(target_os = "windows")]
53 unsafe extern "system" fn rt_thread(
54 _u_timer_id: u32,
55 _u_msg: u32,
56 dw_user: DWORD_PTR,
57 _dw1: DWORD_PTR,
58 _dw2: DWORD_PTR,
59 ) {
60 let ptr = dw_user as *mut Self;
61 if let Some(cb) = &mut (*ptr).cb {
62 cb();
63 }
64 }
65
66 #[cfg(target_os = "linux")]
67 unsafe extern "C" fn rt_thread(_sig: c_int, si: *mut siginfo_t, _uc: *mut c_void) {
68 let ptr = Self::get_ptr(si);
69 let ptr = ptr as *mut Self;
70 if let Some(cb) = &mut (*ptr).cb {
71 cb();
72 }
73 }
74
75 #[cfg(target_os = "linux")]
76 #[allow(deprecated)]
77 unsafe extern "C" fn get_ptr(si: *mut siginfo_t) -> u64 {
78 let ptr_lsb = (*si)._pad[3];
80 let ptr_msb = (*si)._pad[4];
81 ((ptr_msb as u64) << 32) | (ptr_lsb as u64 & 0xFFFF_FFFF)
82 }
83
84 #[cfg(target_os = "macos")]
85 unsafe extern "C" fn rt_thread(ptr: *const c_void) {
86 let ptr = ptr as *mut Self;
87 if let Some(cb) = &mut (*ptr).cb {
88 cb();
89 }
90 }
91}
92
93impl Default for Timer {
94 fn default() -> Self {
95 Self::new()
96 }
97}