use crate::sys::{
QueryPerformanceFrequency,
QueryPerformanceCounter,
LARGE_INTEGER,
CreateTimerQueue,
CreateTimerQueueTimer,
DeleteTimerQueueEx,
DeleteTimerQueueTimer,
ChangeTimerQueueTimer,
HANDLE,
INVALID_HANDLE_VALUE,
WT_EXECUTEINTIMERTHREAD,
WT_EXECUTEINPERSISTENTTHREAD,
WT_EXECUTELONGFUNCTION,
WT_EXECUTEONLYONCE,
WT_TRANSFER_IMPERSONATION,
WAITORTIMERCALLBACK,
c_int,
c_ulong,
c_void,
};
use crate::utils::{self, Result};
use core::{ptr, mem};
pub fn query_performance_frequency() -> Result<i64> {
let mut counter: LARGE_INTEGER = unsafe { mem::zeroed() };
unsafe {
match QueryPerformanceFrequency(&mut counter as *mut _) {
0 => Err(utils::get_last_error()),
_ => Ok(counter.QuadPart)
}
}
}
pub fn query_performance_counter() -> Result<i64> {
let mut counter: LARGE_INTEGER = unsafe { mem::zeroed() };
unsafe {
match QueryPerformanceCounter(&mut counter as *mut _) {
0 => Err(utils::get_last_error()),
_ => Ok(counter.QuadPart)
}
}
}
pub trait CompleteEvent {
#[doc(hidden)]
fn handle() -> HANDLE;
}
pub struct NoWait;
impl CompleteEvent for NoWait {
fn handle() -> HANDLE {
ptr::null_mut()
}
}
pub struct Wait;
impl CompleteEvent for Wait {
fn handle() -> HANDLE {
INVALID_HANDLE_VALUE
}
}
#[derive(Copy, Clone)]
pub struct TimerFlags {
inner: c_ulong
}
pub const DEFAULT_TIMER_FLAGS: TimerFlags = TimerFlags {
inner: 0
};
impl TimerFlags {
pub fn new() -> Self {
DEFAULT_TIMER_FLAGS
}
pub fn on_timer_thread(mut self) -> Self {
self.inner |= WT_EXECUTEINTIMERTHREAD;
self
}
pub fn on_persist(mut self) -> Self {
self.inner |= WT_EXECUTEINPERSISTENTTHREAD;
self
}
pub fn long_fn(mut self) -> Self {
self.inner |= WT_EXECUTELONGFUNCTION;
self
}
pub fn only_once(mut self) -> Self {
self.inner |= WT_EXECUTEONLYONCE;
self
}
pub fn transfer_impersonation(mut self) -> Self {
self.inner |= WT_TRANSFER_IMPERSONATION;
self
}
}
pub struct TimerQueue {
handle: HANDLE
}
impl TimerQueue {
pub fn new() -> Result<Self> {
let handle = unsafe { CreateTimerQueue() };
match handle.is_null() {
true => Err(utils::get_last_error()),
false => Ok(Self { handle })
}
}
#[inline]
fn inner_delete<T: CompleteEvent>(&self) -> c_int {
match self.handle.is_null() {
true => 1,
false => unsafe { DeleteTimerQueueEx(self.handle, T::handle()) },
}
}
pub fn delete<T: CompleteEvent>(self, _event: T) -> Result<()> {
let result = match self.inner_delete::<T>() {
0 => Err(utils::get_last_error()),
_ => Ok(())
};
mem::forget(self);
result
}
pub fn timer(&self, cb: WAITORTIMERCALLBACK, param: *mut c_void, due_time: c_ulong, period: c_ulong, flags: TimerFlags) -> Result<QueueTimer> {
let mut timer: *mut c_void = ptr::null_mut();
match unsafe { CreateTimerQueueTimer(&mut timer as *mut _, self.handle, cb, param, due_time, period, flags.inner) } {
0 => Err(utils::get_last_error()),
_ => Ok(QueueTimer { queue: self.handle, inner: timer })
}
}
}
pub type CallbackType = WAITORTIMERCALLBACK;
pub const DEFAULT_TIMER_QUEUE: TimerQueue = TimerQueue {
handle: ptr::null_mut()
};
impl Default for TimerQueue {
fn default() -> Self {
DEFAULT_TIMER_QUEUE
}
}
impl Drop for TimerQueue {
fn drop(&mut self) {
let _ = self.inner_delete::<NoWait>();
}
}
unsafe impl Send for TimerQueue {}
unsafe impl Sync for TimerQueue {}
pub struct QueueTimer {
queue: HANDLE,
inner: HANDLE,
}
impl QueueTimer {
#[inline]
fn inner_delete<T: CompleteEvent>(&self) -> c_int {
unsafe { DeleteTimerQueueTimer(self.queue, self.inner, T::handle()) }
}
pub unsafe fn cancel<T: CompleteEvent>(&self, _event: T) -> Result<()> {
match self.inner_delete::<T>() {
0 => Err(utils::get_last_error()),
_ => Ok(())
}
}
pub fn reset(&self, due_time: c_ulong, period: c_ulong) -> Result<()> {
match unsafe { ChangeTimerQueueTimer(self.queue, self.inner, due_time, period) } {
0 => Err(utils::get_last_error()),
_ => Ok(())
}
}
pub fn delete<T: CompleteEvent>(self, event: T) -> Result<()> {
let result = unsafe { self.cancel(event) };
mem::forget(self);
result
}
}
impl Drop for QueueTimer {
fn drop(&mut self) {
let _ = self.inner_delete::<NoWait>();
}
}
unsafe impl Send for QueueTimer {}
unsafe impl Sync for QueueTimer {}