std\sys\pal\windows/
time.rs1use crate::ops::Neg;
2use crate::ptr::null;
3use crate::sys::pal::c;
4use crate::time::Duration;
5
6const NANOS_PER_SEC: u64 = 1_000_000_000;
7pub const INTERVALS_PER_SEC: u64 = NANOS_PER_SEC / 100;
8
9pub fn checked_dur2intervals(dur: &Duration) -> Option<i64> {
10 dur.as_secs()
11 .checked_mul(INTERVALS_PER_SEC)?
12 .checked_add(dur.subsec_nanos() as u64 / 100)?
13 .try_into()
14 .ok()
15}
16
17pub fn intervals2dur(intervals: u64) -> Duration {
18 Duration::new(intervals / INTERVALS_PER_SEC, ((intervals % INTERVALS_PER_SEC) * 100) as u32)
19}
20
21pub mod perf_counter {
22 use super::NANOS_PER_SEC;
23 use crate::sync::atomic::{Atomic, AtomicU64, Ordering};
24 use crate::sys::{c, cvt};
25 use crate::time::Duration;
26
27 pub fn now() -> i64 {
28 let mut qpc_value: i64 = 0;
29 cvt(unsafe { c::QueryPerformanceCounter(&mut qpc_value) }).unwrap();
30 qpc_value
31 }
32
33 pub fn frequency() -> i64 {
34 static FREQUENCY: Atomic<u64> = AtomicU64::new(0);
39
40 let cached = FREQUENCY.load(Ordering::Relaxed);
41 if cached != 0 {
43 return cached as i64;
44 }
45 let mut frequency = 0;
47 unsafe {
48 cvt(c::QueryPerformanceFrequency(&mut frequency)).unwrap();
49 }
50
51 FREQUENCY.store(frequency as u64, Ordering::Relaxed);
52 frequency
53 }
54
55 pub fn epsilon() -> Duration {
60 let epsilon = NANOS_PER_SEC / (frequency() as u64);
61 Duration::from_nanos(epsilon)
62 }
63}
64
65pub(crate) struct WaitableTimer {
67 handle: c::HANDLE,
68}
69
70impl WaitableTimer {
71 pub fn high_resolution() -> Result<Self, ()> {
73 let handle = unsafe {
74 c::CreateWaitableTimerExW(
75 null(),
76 null(),
77 c::CREATE_WAITABLE_TIMER_HIGH_RESOLUTION,
78 c::TIMER_ALL_ACCESS,
79 )
80 };
81 if !handle.is_null() { Ok(Self { handle }) } else { Err(()) }
82 }
83
84 pub fn set(&self, duration: Duration) -> Result<(), ()> {
85 let time = checked_dur2intervals(&duration).ok_or(())?.neg();
89 let result = unsafe { c::SetWaitableTimer(self.handle, &time, 0, None, null(), c::FALSE) };
90 if result != 0 { Ok(()) } else { Err(()) }
91 }
92
93 pub fn wait(&self) -> Result<(), ()> {
94 let result = unsafe { c::WaitForSingleObject(self.handle, c::INFINITE) };
95 if result != c::WAIT_FAILED { Ok(()) } else { Err(()) }
96 }
97}
98
99impl Drop for WaitableTimer {
100 fn drop(&mut self) {
101 unsafe { c::CloseHandle(self.handle) };
102 }
103}