use core::num::NonZeroU64;
use std::sync::OnceLock;
use windows_sys::Win32::System::Performance::{QueryPerformanceCounter, QueryPerformanceFrequency};
use crate::clock::{Clock, Steady};
use crate::timeline::{TimePoint, Timeline};
#[cfg(test)]
mod tests;
pub enum PerformanceCounter {}
impl Timeline for PerformanceCounter {
fn ticks_per_second() -> NonZeroU64 {
static FREQUENCY: OnceLock<NonZeroU64> = OnceLock::new();
*FREQUENCY.get_or_init(frequency)
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct PerformanceClock;
impl Clock for PerformanceClock {
type Timeline = PerformanceCounter;
fn now(&self) -> TimePoint<PerformanceCounter> {
let mut ticks = 0;
let succeeded = unsafe { QueryPerformanceCounter(&mut ticks) };
debug_assert_ne!(succeeded, 0, "QueryPerformanceCounter failed");
TimePoint::from_ticks(ticks.cast_unsigned())
}
}
impl Steady for PerformanceClock {}
fn frequency() -> NonZeroU64 {
let mut per_second = 0;
let succeeded = unsafe { QueryPerformanceFrequency(&mut per_second) };
assert_ne!(succeeded, 0, "QueryPerformanceFrequency failed");
NonZeroU64::new(per_second.cast_unsigned()).expect("a performance counter frequency of zero")
}