Skip to main content

polyoxide_rt/
runtime.rs

1//! The `Runtime` trait.
2
3use std::fmt;
4use std::time::Duration;
5
6use crate::{BoxFuture, Instant};
7
8/// What a polyoxide crate needs of an async runtime: a detached spawn, a
9/// sleep, a yield to the host, and a monotonic clock. Everything else in this
10/// crate (`spawn`'s `Task`, `timeout`, `Interval`) is built on these, so an
11/// implementor writes only these.
12///
13/// A client takes its runtime from its builder, and falls back to
14/// `default_runtime()`; nothing is process-wide.
15pub trait Runtime: Send + Sync + fmt::Debug + 'static {
16    /// Run `task` to completion, detached.
17    fn spawn(&self, task: BoxFuture<()>);
18
19    /// Complete after `duration`. Any duration, `Duration::MAX` included, is
20    /// valid.
21    fn sleep(&self, duration: Duration) -> BoxFuture<()>;
22
23    /// Hand the thread back to the host once: work already queued (other
24    /// tasks, I/O callbacks, a browser's messages) runs before the caller
25    /// continues, and no timer is involved.
26    ///
27    /// It has no default because nothing generic really yields: re-waking the
28    /// task at once only re-queues it, which under a browser's microtask queue
29    /// never reaches the event loop, and a zero sleep is no timer at all
30    /// there. Tokio's runtime defers to `tokio::task::yield_now`; the
31    /// browser's resumes on the next macrotask, through a `MessageChannel`
32    /// post, which no timer clamp delays.
33    fn yield_now(&self) -> BoxFuture<()>;
34
35    /// The runtime's monotonic clock.
36    fn now(&self) -> Instant;
37
38    /// Complete at `deadline`, at once when it has passed.
39    fn sleep_until(&self, deadline: Instant) -> BoxFuture<()> {
40        self.sleep(deadline.saturating_duration_since(self.now()))
41    }
42}