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}