use windows::Win32::{Media::*, System::Threading::*};
use crate::error::TimerError;
pub struct NativeTimerWrapper {
timer_id: u32,
}
impl NativeTimerWrapper {
pub fn new() -> NativeTimerWrapper {
NativeTimerWrapper { timer_id: 0 }
}
pub fn start<P>(
&mut self,
cb: LPTIMECALLBACK,
period_ns: u32,
lp_param: *mut P,
) -> Result<bool, TimerError> {
unsafe {
let h_process = GetCurrentProcess();
SetPriorityClass(h_process, REALTIME_PRIORITY_CLASS);
let u_resolution = 1;
timeBeginPeriod(u_resolution);
let timer_id = timeSetEvent(
period_ns / 1000 / 1000,
u_resolution,
cb,
lp_param as usize,
TIME_PERIODIC | TIME_CALLBACK_FUNCTION | TIME_KILL_SYNCHRONOUS,
);
if timer_id == 0 {
return Err(TimerError::CreationFailed());
}
self.timer_id = timer_id;
Ok(true)
}
}
pub fn close(&mut self) -> Result<(), TimerError> {
unsafe {
if self.timer_id != 0 && timeKillEvent(self.timer_id) != TIMERR_NOERROR {
return Err(TimerError::DeleteFailed());
}
timeEndPeriod(1);
}
Ok(())
}
}
impl Drop for NativeTimerWrapper {
fn drop(&mut self) {
let _ = self.close();
}
}