use crate::core::Timestamp;
use core::marker::PhantomData;
use std::time::{Duration, Instant};
const DEFAULT_CLOCK_ID: u64 = 0;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ClockId(u64);
impl Default for ClockId {
fn default() -> Self {
ClockId(DEFAULT_CLOCK_ID)
}
}
impl ClockId {
pub fn as_u64(&self) -> u64 {
self.0
}
}
impl ClockId {
pub fn is_default(&self) -> bool {
self.0 == DEFAULT_CLOCK_ID
}
}
pub trait Clock<M> {
fn now(&self) -> Timestamp<M>;
}
#[derive(Clone)]
pub struct AppMonotonicClock<M> {
reference: Instant,
_marker: PhantomData<M>,
}
impl<M> Clock<M> for AppMonotonicClock<M> {
fn now(&self) -> Timestamp<M> {
Timestamp::new(self.reference.elapsed())
}
}
impl<M> AppMonotonicClock<M> {
pub fn new() -> Self {
Self {
reference: Instant::now(),
_marker: PhantomData,
}
}
}
impl<M> Default for AppMonotonicClock<M> {
fn default() -> Self {
AppMonotonicClock::new()
}
}
#[derive(Clone)]
pub struct SysMonotonicClock<M> {
_marker: PhantomData<M>,
}
impl<M> Clock<M> for SysMonotonicClock<M> {
fn now(&self) -> Timestamp<M> {
get_monotonic_time().into()
}
}
impl<M> SysMonotonicClock<M> {
pub fn new() -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<M> Default for SysMonotonicClock<M> {
fn default() -> Self {
SysMonotonicClock::new()
}
}
fn get_monotonic_time() -> Duration {
#[cfg(unix)]
{
use nix::time::{clock_gettime, ClockId};
let time = clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap();
Duration::from(time)
}
#[cfg(windows)]
{
use std::{mem::MaybeUninit, sync::Once};
use windows_sys::Win32::System::Performance::{
QueryPerformanceCounter, QueryPerformanceFrequency,
};
static mut FREQUENCY: i64 = 0;
static INIT: Once = Once::new();
unsafe {
INIT.call_once(|| {
let mut freq = MaybeUninit::<i64>::uninit();
if QueryPerformanceFrequency(freq.as_mut_ptr()) == 0 {
panic!("QueryPerformanceFrequency failed");
}
FREQUENCY = freq.assume_init();
});
let mut counter = MaybeUninit::<i64>::uninit();
if QueryPerformanceCounter(counter.as_mut_ptr()) == 0 {
panic!("QueryPerformanceCounter failed");
}
let count = counter.assume_init();
Duration::from_secs_f64(count as f64 / FREQUENCY as f64)
}
}
}