Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wasi/src/p2/host/clocks.rs
3073 views
1
use crate::clocks::WasiClocksCtxView;
2
use crate::p2::DynPollable;
3
use crate::p2::bindings::{
4
clocks::monotonic_clock::{self, Duration as WasiDuration, Instant},
5
clocks::wall_clock::{self, Datetime},
6
};
7
use cap_std::time::SystemTime;
8
use std::time::Duration;
9
use wasmtime::component::Resource;
10
use wasmtime_wasi_io::poll::{Pollable, subscribe};
11
12
impl TryFrom<crate::clocks::Datetime> for Datetime {
13
type Error = crate::clocks::DatetimeError;
14
15
fn try_from(
16
crate::clocks::Datetime {
17
seconds,
18
nanoseconds,
19
}: crate::clocks::Datetime,
20
) -> Result<Self, Self::Error> {
21
Ok(Self {
22
seconds: seconds.try_into()?,
23
nanoseconds,
24
})
25
}
26
}
27
28
impl TryFrom<Datetime> for crate::clocks::Datetime {
29
type Error = crate::clocks::DatetimeError;
30
31
fn try_from(
32
Datetime {
33
seconds,
34
nanoseconds,
35
}: Datetime,
36
) -> Result<Self, Self::Error> {
37
Ok(Self {
38
seconds: seconds.try_into()?,
39
nanoseconds,
40
})
41
}
42
}
43
44
impl TryFrom<SystemTime> for Datetime {
45
type Error = crate::clocks::DatetimeError;
46
47
fn try_from(time: SystemTime) -> Result<Self, Self::Error> {
48
let time = crate::clocks::Datetime::try_from(time)?;
49
time.try_into()
50
}
51
}
52
53
impl wall_clock::Host for WasiClocksCtxView<'_> {
54
fn now(&mut self) -> wasmtime::Result<Datetime> {
55
let now = self.ctx.wall_clock.now();
56
Ok(Datetime {
57
seconds: now.as_secs(),
58
nanoseconds: now.subsec_nanos(),
59
})
60
}
61
62
fn resolution(&mut self) -> wasmtime::Result<Datetime> {
63
let res = self.ctx.wall_clock.resolution();
64
Ok(Datetime {
65
seconds: res.as_secs(),
66
nanoseconds: res.subsec_nanos(),
67
})
68
}
69
}
70
71
fn subscribe_to_duration(
72
table: &mut wasmtime::component::ResourceTable,
73
duration: tokio::time::Duration,
74
) -> wasmtime::Result<Resource<DynPollable>> {
75
let sleep = if duration.is_zero() {
76
table.push(Deadline::Past)?
77
} else if let Some(deadline) = tokio::time::Instant::now().checked_add(duration) {
78
// NB: this resource created here is not actually exposed to wasm, it's
79
// only an internal implementation detail used to match the signature
80
// expected by `subscribe`.
81
table.push(Deadline::Instant(deadline))?
82
} else {
83
// If the user specifies a time so far in the future we can't
84
// represent it, wait forever rather than trap.
85
table.push(Deadline::Never)?
86
};
87
subscribe(table, sleep)
88
}
89
90
impl monotonic_clock::Host for WasiClocksCtxView<'_> {
91
fn now(&mut self) -> wasmtime::Result<Instant> {
92
Ok(self.ctx.monotonic_clock.now())
93
}
94
95
fn resolution(&mut self) -> wasmtime::Result<Instant> {
96
Ok(self.ctx.monotonic_clock.resolution())
97
}
98
99
fn subscribe_instant(&mut self, when: Instant) -> wasmtime::Result<Resource<DynPollable>> {
100
let clock_now = self.ctx.monotonic_clock.now();
101
let duration = if when > clock_now {
102
Duration::from_nanos(when - clock_now)
103
} else {
104
Duration::from_nanos(0)
105
};
106
subscribe_to_duration(self.table, duration)
107
}
108
109
fn subscribe_duration(
110
&mut self,
111
duration: WasiDuration,
112
) -> wasmtime::Result<Resource<DynPollable>> {
113
subscribe_to_duration(self.table, Duration::from_nanos(duration))
114
}
115
}
116
117
enum Deadline {
118
Past,
119
Instant(tokio::time::Instant),
120
Never,
121
}
122
123
#[async_trait::async_trait]
124
impl Pollable for Deadline {
125
async fn ready(&mut self) {
126
match self {
127
Deadline::Past => {}
128
Deadline::Instant(instant) => tokio::time::sleep_until(*instant).await,
129
Deadline::Never => std::future::pending().await,
130
}
131
}
132
}
133
134