Skip to main content

gpu_async_reactor/core/
time.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! Time ports (SBIO): the core reads time only through [`Clock`] and sleeps only through
4//! [`Timer`], so a host can replay any wait from virtual time and two hosts given the same clock
5//! produce the same decisions.
6
7/// Monotonic nanoseconds from a host-chosen origin.
8#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub struct MonoNs(pub u64);
10
11/// A duration in nanoseconds.
12#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub struct DurNs(pub u64);
14
15impl MonoNs {
16    /// The time from `earlier` to `self` (0 if `earlier` is later).
17    #[must_use]
18    pub const fn since(self, earlier: MonoNs) -> DurNs {
19        DurNs(self.0.saturating_sub(earlier.0))
20    }
21
22    /// `self + d`, saturating.
23    #[must_use]
24    pub const fn after(self, d: DurNs) -> MonoNs {
25        MonoNs(self.0.saturating_add(d.0))
26    }
27}
28
29/// The host's monotonic clock: the core's only time source.
30pub trait Clock {
31    /// Monotonic nanoseconds from the host's origin.
32    fn monotonic_ns(&self) -> MonoNs;
33}
34
35/// The host's sleep. A host that runs a wait inline returns a future that is ready on its first
36/// poll (it slept already); an executor's timer pends until its deadline.
37#[expect(
38    async_fn_in_trait,
39    reason = "the waiter is single-threaded by design; no Send bound is wanted"
40)]
41pub trait Timer {
42    /// Resolves once the host clock reads `at` or later.
43    async fn sleep_until(&self, at: MonoNs);
44}
45
46impl<C: Clock + ?Sized> Clock for &C {
47    fn monotonic_ns(&self) -> MonoNs {
48        (**self).monotonic_ns()
49    }
50}