Skip to main content

Timer

Trait Timer 

Source
pub trait Timer {
    type Instant: Copy + PartialOrd;
    type Sleep: Future<Output = ()>;

    // Required methods
    fn sleep(&self, d: Duration) -> Self::Sleep;
    fn now(&self) -> Self::Instant;
    fn elapsed_since(&self, earlier: Self::Instant) -> Duration;
}
Expand description

Timer is defined once, in hclient-core: the portable core needs it for timeouts and backoff. This is just a re-export.

Discard comes with it: Timer::Sleep is a named associated type, and a runtime whose native timer resolves to something other than () — as async_io::Timer does — needs the adapter to satisfy it. Re-exported here so a runtime crate does not have to depend on hclient-core directly just to name one wrapper. The one runtime capability the portable core needs: timeouts and backoff. Networking and spawning live in the transports.

Not hyper::rt::Timer: that one has Sleep: Send + Sync unconditionally, sleep() returns Pin<Box<dyn Sleep>> (an allocation per sleep), and now() is typed on std::time::Instant, which panics on wasm32-unknown-unknown.

§Why Timer::Sleep is an associated type and not impl Future

An RPITIT — fn sleep(&self, d: Duration) -> impl Future<Output = ()> — is more comfortable to write and costs two things:

  • A struct cannot hold a sleep. It has no name to store, so a body wrapper can only check elapsed time on each poll_frame, which structurally cannot cut a response body that goes completely silent after the head: nothing wakes the wrapper, so nothing ever looks at the clock again. Measured with a counting waker and no executor running, that shape registers zero wakes; a stored sleep registers one. hclient::body::Deadline holds a Pin<Box<Tm::Sleep>> for exactly this reason.
  • Generic code cannot spawn a background task. hclient_rt::Spawn<F> takes the future as a type parameter, so a bound has to name it, and an anonymous future has no name. See hclient-native’s pool module doc.

It also hides a third thing, the one most likely to be mistaken for a bug: a backend whose native timer resolves to something other than (), which async { t.await; } discards silently. Naming the type makes that visible, and Discard is the adapter for it.

TcpConnect::Stream is the same idea applied to a socket; this is not a new shape in the seam.

Required Associated Types§

Source

type Instant: Copy + PartialOrd

Source

type Sleep: Future<Output = ()>

The future Timer::sleep returns, named.

Sendness is deliberately not required here, exactly as it is not required of Timer itself: a caller that needs a Send sleep gets it because its own clock’s Sleep happens to be Send, inferred rather than declared.

Required Methods§

Source

fn sleep(&self, d: Duration) -> Self::Sleep

Source

fn now(&self) -> Self::Instant

Source

fn elapsed_since(&self, earlier: Self::Instant) -> Duration

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§