use crate::platform::PlatformClock;
use crate::types::Ticks;
const NANOSECONDS_PER_SECOND: u128 = 1_000_000_000;
#[derive(Debug, Default, Clone, Copy)]
pub struct NoStdLinuxMonotonicClock;
impl NoStdLinuxMonotonicClock {
#[inline]
pub const fn new() -> NoStdLinuxMonotonicClock {
NoStdLinuxMonotonicClock
}
#[allow(unsafe_code)]
#[inline]
fn read_monotonic_nanoseconds() -> u64 {
let mut timespec_value = libc::timespec {
tv_sec: 0,
tv_nsec: 0,
};
let return_code =
unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut timespec_value) };
if return_code != 0 {
return 0;
}
if timespec_value.tv_sec < 0 as libc::time_t {
return 0;
}
if timespec_value.tv_nsec < 0 as libc::c_long
|| timespec_value.tv_nsec >= 1_000_000_000 as libc::c_long
{
return 0;
}
let seconds_as_u64 = timespec_value.tv_sec as u64;
let nanoseconds_as_u64 = timespec_value.tv_nsec as u64;
let total_nanoseconds_as_u128 = (seconds_as_u64 as u128)
.saturating_mul(NANOSECONDS_PER_SECOND)
.saturating_add(nanoseconds_as_u64 as u128);
if total_nanoseconds_as_u128 > u64::MAX as u128 {
u64::MAX
} else {
total_nanoseconds_as_u128 as u64
}
}
}
impl PlatformClock for NoStdLinuxMonotonicClock {
#[inline]
fn now_ticks(&self) -> Ticks {
Ticks::new(Self::read_monotonic_nanoseconds())
}
#[inline]
fn ticks_to_nanos(&self, ticks: Ticks) -> u64 {
*ticks.as_u64()
}
#[inline]
fn nanos_to_ticks(&self, nanoseconds: u64) -> Ticks {
Ticks::new(nanoseconds)
}
}
#[cfg(feature = "std")]
#[derive(Debug, Clone)]
pub struct StdLinuxMonotonicClock {
origin: std::time::Instant,
}
#[cfg(feature = "std")]
impl StdLinuxMonotonicClock {
#[inline]
pub fn new() -> StdLinuxMonotonicClock {
StdLinuxMonotonicClock {
origin: std::time::Instant::now(),
}
}
}
#[cfg(feature = "std")]
impl Default for StdLinuxMonotonicClock {
#[inline]
fn default() -> StdLinuxMonotonicClock {
StdLinuxMonotonicClock::new()
}
}
#[cfg(feature = "std")]
impl PlatformClock for StdLinuxMonotonicClock {
#[inline]
fn now_ticks(&self) -> Ticks {
let duration_since_origin = std::time::Instant::now().duration_since(self.origin);
let total_nanoseconds_as_u128 = duration_since_origin.as_nanos();
if total_nanoseconds_as_u128 > u64::MAX as u128 {
Ticks::new(u64::MAX)
} else {
Ticks::new(total_nanoseconds_as_u128 as u64)
}
}
#[inline]
fn ticks_to_nanos(&self, ticks: Ticks) -> u64 {
*ticks.as_u64()
}
#[inline]
fn nanos_to_ticks(&self, nanoseconds: u64) -> Ticks {
Ticks::new(nanoseconds)
}
}