use windows_sys::Win32::{
Foundation::FILETIME,
System::Threading::{
CloseThreadpoolTimer, CreateThreadpoolTimer, PTP_TIMER, PTP_TIMER_CALLBACK,
SetThreadpoolTimer, WaitForThreadpoolTimerCallbacks,
},
};
pub(crate) struct ThreadpoolTimer {
handle: PTP_TIMER,
}
unsafe impl Send for ThreadpoolTimer {}
unsafe impl Sync for ThreadpoolTimer {}
impl ThreadpoolTimer {
pub(crate) unsafe fn new(
callback: PTP_TIMER_CALLBACK,
context: *mut core::ffi::c_void,
) -> Option<Self> {
let h = unsafe { CreateThreadpoolTimer(callback, context, std::ptr::null()) };
if h == 0 as PTP_TIMER {
None
} else {
Some(Self { handle: h })
}
}
pub(crate) fn set_relative(&self, due_in_ticks: Option<i64>) {
match due_in_ticks {
Some(ticks) => {
let neg = -ticks;
let ft = FILETIME {
dwLowDateTime: neg as u32,
dwHighDateTime: (neg >> 32) as u32,
};
unsafe { SetThreadpoolTimer(self.handle, &raw const ft, 0, 0) };
}
None => {
unsafe { SetThreadpoolTimer(self.handle, std::ptr::null(), 0, 0) };
}
}
}
#[cfg(debug_assertions)]
pub(crate) fn as_raw(&self) -> PTP_TIMER {
self.handle
}
}
impl Drop for ThreadpoolTimer {
fn drop(&mut self) {
self.set_relative(None);
unsafe {
WaitForThreadpoolTimerCallbacks(self.handle, 1);
CloseThreadpoolTimer(self.handle);
}
}
}