Path: blob/main/crates/wasi/src/p2/host/clocks.rs
3073 views
use crate::clocks::WasiClocksCtxView;1use crate::p2::DynPollable;2use crate::p2::bindings::{3clocks::monotonic_clock::{self, Duration as WasiDuration, Instant},4clocks::wall_clock::{self, Datetime},5};6use cap_std::time::SystemTime;7use std::time::Duration;8use wasmtime::component::Resource;9use wasmtime_wasi_io::poll::{Pollable, subscribe};1011impl TryFrom<crate::clocks::Datetime> for Datetime {12type Error = crate::clocks::DatetimeError;1314fn try_from(15crate::clocks::Datetime {16seconds,17nanoseconds,18}: crate::clocks::Datetime,19) -> Result<Self, Self::Error> {20Ok(Self {21seconds: seconds.try_into()?,22nanoseconds,23})24}25}2627impl TryFrom<Datetime> for crate::clocks::Datetime {28type Error = crate::clocks::DatetimeError;2930fn try_from(31Datetime {32seconds,33nanoseconds,34}: Datetime,35) -> Result<Self, Self::Error> {36Ok(Self {37seconds: seconds.try_into()?,38nanoseconds,39})40}41}4243impl TryFrom<SystemTime> for Datetime {44type Error = crate::clocks::DatetimeError;4546fn try_from(time: SystemTime) -> Result<Self, Self::Error> {47let time = crate::clocks::Datetime::try_from(time)?;48time.try_into()49}50}5152impl wall_clock::Host for WasiClocksCtxView<'_> {53fn now(&mut self) -> wasmtime::Result<Datetime> {54let now = self.ctx.wall_clock.now();55Ok(Datetime {56seconds: now.as_secs(),57nanoseconds: now.subsec_nanos(),58})59}6061fn resolution(&mut self) -> wasmtime::Result<Datetime> {62let res = self.ctx.wall_clock.resolution();63Ok(Datetime {64seconds: res.as_secs(),65nanoseconds: res.subsec_nanos(),66})67}68}6970fn subscribe_to_duration(71table: &mut wasmtime::component::ResourceTable,72duration: tokio::time::Duration,73) -> wasmtime::Result<Resource<DynPollable>> {74let sleep = if duration.is_zero() {75table.push(Deadline::Past)?76} else if let Some(deadline) = tokio::time::Instant::now().checked_add(duration) {77// NB: this resource created here is not actually exposed to wasm, it's78// only an internal implementation detail used to match the signature79// expected by `subscribe`.80table.push(Deadline::Instant(deadline))?81} else {82// If the user specifies a time so far in the future we can't83// represent it, wait forever rather than trap.84table.push(Deadline::Never)?85};86subscribe(table, sleep)87}8889impl monotonic_clock::Host for WasiClocksCtxView<'_> {90fn now(&mut self) -> wasmtime::Result<Instant> {91Ok(self.ctx.monotonic_clock.now())92}9394fn resolution(&mut self) -> wasmtime::Result<Instant> {95Ok(self.ctx.monotonic_clock.resolution())96}9798fn subscribe_instant(&mut self, when: Instant) -> wasmtime::Result<Resource<DynPollable>> {99let clock_now = self.ctx.monotonic_clock.now();100let duration = if when > clock_now {101Duration::from_nanos(when - clock_now)102} else {103Duration::from_nanos(0)104};105subscribe_to_duration(self.table, duration)106}107108fn subscribe_duration(109&mut self,110duration: WasiDuration,111) -> wasmtime::Result<Resource<DynPollable>> {112subscribe_to_duration(self.table, Duration::from_nanos(duration))113}114}115116enum Deadline {117Past,118Instant(tokio::time::Instant),119Never,120}121122#[async_trait::async_trait]123impl Pollable for Deadline {124async fn ready(&mut self) {125match self {126Deadline::Past => {}127Deadline::Instant(instant) => tokio::time::sleep_until(*instant).await,128Deadline::Never => std::future::pending().await,129}130}131}132133134