Skip to content

Added compatibility with std #112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/clocks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ mod counter;
pub use self::counter::Counter;

mod monotonic;
pub(crate) use self::monotonic::{to_std_instant, from_std_instant};
pub use self::monotonic::Monotonic;
8 changes: 8 additions & 0 deletions src/clocks/monotonic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,26 @@
mod windows;
#[cfg(target_os = "windows")]
pub use self::windows::Monotonic;
#[cfg(target_os = "windows")]
pub(crate) use self::windows::{to_std_instant, from_std_instant};

#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
mod wasm_browser;
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
pub use self::wasm_browser::Monotonic;
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
pub(crate) use self::wasm_browser::{to_std_instant, from_std_instant};

#[cfg(all(target_arch = "wasm32", target_os = "wasi"))]
mod wasm_wasi;
#[cfg(all(target_arch = "wasm32", target_os = "wasi"))]
pub use self::wasm_wasi::Monotonic;
#[cfg(all(target_arch = "wasm32", target_os = "wasi"))]
pub(crate) use self::wasm_wasi::{to_std_instant, from_std_instant};

#[cfg(not(any(target_os = "windows", target_arch = "wasm32")))]
mod unix;
#[cfg(not(any(target_os = "windows", target_arch = "wasm32")))]
pub use self::unix::Monotonic;
#[cfg(not(any(target_os = "windows", target_arch = "wasm32")))]
pub(crate) use self::unix::{to_std_instant, from_std_instant};
39 changes: 39 additions & 0 deletions src/clocks/monotonic/unix.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use std::mem;
use std::time::Duration;

#[derive(Clone, Copy, Debug, Default)]
pub struct Monotonic {
_default: (),
Expand Down Expand Up @@ -36,3 +39,39 @@ impl Monotonic {
ts.tv_sec as u64 * 1_000_000_000 + ts.tv_nsec as u64
}
}

// std::time::Instant is represented as
// struct Nanoseconds(u32);
//
// struct Timespec {
// tv_sec: i64,
// tv_nsec: Nanoseconds,
// }

// struct Instant {
// t: Timespec,
// }

struct Nanoseconds(u32);

struct Timespec {
tv_sec: i64,
tv_nsec: Nanoseconds,
}

pub(crate) fn to_std_instant(instant: u64) -> std::time::Instant {
let dur = Duration::from_nanos(instant);

unsafe {
mem::transmute(Timespec {
tv_sec: dur.as_secs() as i64,
tv_nsec: Nanoseconds(dur.subsec_nanos()),
})
}
}

pub(crate) fn from_std_instant(instant: std::time::Instant) -> u64 {
let ts: Timespec = unsafe { mem::transmute(instant) };

ts.tv_sec as u64 * 1_000_000_000 + ts.tv_nsec.0 as u64
}
17 changes: 16 additions & 1 deletion src/clocks/monotonic/wasm_browser.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::cell::OnceCell;

use std::mem;
use std::time::Duration;
use web_sys::{
js_sys::Reflect,
wasm_bindgen::{JsCast, JsValue},
Expand Down Expand Up @@ -37,3 +38,17 @@ impl Monotonic {
f64::trunc(now * 1_000_000.0) as u64
}
}


// std::time::Instant is represented as
// struct Instant(std::time::Duration);

pub(crate) fn to_std_instant(instant: u64) -> std::time::Instant {
unsafe { mem::transmute(Duration::from_nanos(instant)) }
}

pub(crate) fn from_std_instant(instant: std::time::Instant) -> u64 {
let dur: Duration = unsafe { mem::transmute(instant) };

dur.as_secs() * 1_000_000_000 + dur.subsec_nanos()
}
16 changes: 16 additions & 0 deletions src/clocks/monotonic/wasm_wasi.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use std::mem;
use std::time::Duration;

#[derive(Clone, Copy, Debug, Default)]
pub struct Monotonic {
_default: (),
Expand All @@ -8,3 +11,16 @@ impl Monotonic {
unsafe { wasi::clock_time_get(wasi::CLOCKID_MONOTONIC, 1).expect("failed to get time") }
}
}

// std::time::Instant is represented as
// struct Instant(std::time::Duration);

pub(crate) fn to_std_instant(instant: u64) -> std::time::Instant {
unsafe { mem::transmute(Duration::from_nanos(instant)) }
}

pub(crate) fn from_std_instant(instant: std::time::Instant) -> u64 {
let dur: Duration = unsafe { mem::transmute(instant) };

dur.as_secs() * 1_000_000_000 + dur.subsec_nanos()
}
16 changes: 16 additions & 0 deletions src/clocks/monotonic/windows.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::mem;
use std::time::Duration;
use winapi::um::profileapi;

#[derive(Clone, Copy, Debug)]
Expand Down Expand Up @@ -40,3 +41,18 @@ impl Default for Monotonic {
}
}
}

// std::time::Instant is represented as
// struct Instant {
// t: Duration,
// }

pub(crate) fn to_std_instant(instant: u64) -> std::time::Instant {
unsafe { mem::transmute(Duration::from_nanos(instant)) }
}

pub(crate) fn from_std_instant(instant: std::time::Instant) -> u64 {
let dur: Duration = unsafe { mem::transmute(instant) };

dur.as_secs() * 1_000_000_000 + dur.subsec_nanos()
}
4 changes: 2 additions & 2 deletions src/detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ pub fn has_counter_support() -> bool {
let cpuid = raw_cpuid::CpuId::new();
let has_invariant_tsc = cpuid
.get_advanced_power_mgmt_info()
.map_or(false, |apm| apm.has_invariant_tsc());
.is_some_and(|apm| apm.has_invariant_tsc());
let has_rdtscp = cpuid
.get_extended_processor_and_feature_identifiers()
.map_or(false, |epf| epf.has_rdtscp());
.is_some_and(|epf| epf.has_rdtscp());

has_invariant_tsc && has_rdtscp
}
Expand Down
60 changes: 54 additions & 6 deletions src/instant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::cmp::{Ord, Ordering, PartialOrd};
use std::fmt;
use std::ops::{Add, AddAssign, Sub, SubAssign};
use std::time::Duration;
use crate::clocks::{from_std_instant, to_std_instant};

/// A point-in-time wall-clock measurement.
///
Expand Down Expand Up @@ -84,8 +85,8 @@ impl Instant {
/// let new_now = clock.now();
/// println!("{:?}", new_now.duration_since(now));
/// ```
pub fn duration_since(&self, earlier: Instant) -> Duration {
self.checked_duration_since(earlier).unwrap_or_default()
pub fn duration_since(&self, earlier: impl Into<Instant>) -> Duration {
self.checked_duration_since(earlier.into()).unwrap_or_default()
}

/// Returns the amount of time elapsed from another instant to this one, or `None` if that
Expand All @@ -110,8 +111,8 @@ impl Instant {
/// println!("{:?}", new_now.checked_duration_since(now));
/// println!("{:?}", now.checked_duration_since(new_now)); // None
/// ```
pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
self.0.checked_sub(earlier.0).map(Duration::from_nanos)
pub fn checked_duration_since(&self, earlier: impl Into<Instant>) -> Option<Duration> {
self.0.checked_sub(earlier.into().0).map(Duration::from_nanos)
}

/// Returns the amount of time elapsed from another instant to this one, or zero duration if
Expand All @@ -136,8 +137,8 @@ impl Instant {
/// println!("{:?}", new_now.saturating_duration_since(now));
/// println!("{:?}", now.saturating_duration_since(new_now)); // 0ns
/// ```
pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
self.checked_duration_since(earlier).unwrap_or_default()
pub fn saturating_duration_since(&self, earlier: impl Into<Instant>) -> Duration {
self.checked_duration_since(earlier.into()).unwrap_or_default()
}

/// Returns the amount of time elapsed since this instant was created.
Expand Down Expand Up @@ -277,6 +278,18 @@ impl Into<prost_types::Timestamp> for Instant {
}
}

impl From<Instant> for std::time::Instant {
fn from(val: Instant) -> Self {
to_std_instant(val.0)
}
}

impl From<std::time::Instant> for Instant {
fn from(val: std::time::Instant) -> Self {
Instant(from_std_instant(val))
}
}

#[cfg(test)]
mod tests {
use once_cell::sync::Lazy;
Expand All @@ -294,6 +307,8 @@ mod tests {
ignore = "WASM thread cannot sleep"
)]
fn test_now() {
let _guard = RECENT_LOCK.lock().unwrap();

let t0 = Instant::now();
thread::sleep(Duration::from_millis(15));
let t1 = Instant::now();
Expand Down Expand Up @@ -390,6 +405,8 @@ mod tests {
dur
}

let _guard = RECENT_LOCK.lock().unwrap();

let dur = nanos_to_dur(1 << 64);
let now = Instant::now();

Expand All @@ -400,4 +417,35 @@ mod tests {
assert_ne!(Some(now), behind);
assert_ne!(Some(now), ahead);
}

#[test]
fn test_into_std_instant() {
let _guard = RECENT_LOCK.lock().unwrap();

let instant = Instant::now();
let std_instant: std::time::Instant = instant.into();
let instant_from_std: Instant = std_instant.into();

assert_eq!(instant, instant_from_std);

thread::sleep(Duration::from_millis(1));

let now = Instant::now();

assert_eq!(
now.duration_since(instant),
now.duration_since(std_instant)
);
}

#[test]
fn test_from_std_instant() {
let _guard = RECENT_LOCK.lock().unwrap();

let std_instant: std::time::Instant = std::time::Instant::now();
let instant: Instant = std_instant.into();
let std_instant_from_instant: std::time::Instant = instant.into();

assert_eq!(std_instant, std_instant_from_instant);
}
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ static GLOBAL_CALIBRATION: OnceCell<Calibration> = OnceCell::new();

// Per-thread clock override, used by `quanta::with_clock`, `Instant::now`, and sometimes `Instant::recent`.
thread_local! {
static CLOCK_OVERRIDE: RefCell<Option<Clock>> = RefCell::new(None);
static CLOCK_OVERRIDE: RefCell<Option<Clock>> = const { RefCell::new(None) };
}

// Run 500 rounds of calibration before we start actually seeing what the numbers look like.
Expand Down