1cfg_time!(
2 mod after;
3 mod delay;
4 mod interval;
5 mod sleep;
6 mod timeout;
7
8 pub use after::*;
9 pub use delay::*;
10 pub use interval::*;
11 pub use sleep::*;
12 pub use timeout::*;
13
14 use std::time::{Duration, Instant};
15);
16
17use core::{
18 future::Future,
19 pin::Pin,
20 task::{Context, Poll},
21};
22
23use wasm::channel::*;
24
25use super::handle::JoinError;
26use crate::{AsyncBlockingSpawner, AsyncLocalSpawner, AsyncSpawner, Yielder};
27
28pub struct JoinHandle<F> {
30 pub(crate) stop_tx: oneshot::Sender<bool>,
31 pub(crate) rx: oneshot::Receiver<F>,
32}
33
34impl<F> Future for JoinHandle<F> {
35 type Output = Result<F, JoinError>;
36
37 fn poll(
38 mut self: core::pin::Pin<&mut Self>,
39 cx: &mut core::task::Context<'_>,
40 ) -> core::task::Poll<Self::Output> {
41 core::pin::Pin::new(&mut self.rx)
42 .poll(cx)
43 .map(|res| res.map_err(|_| JoinError::new()))
44 }
45}
46
47impl<F> JoinHandle<F> {
48 #[inline]
50 pub fn detach(self) {
51 let _ = self.stop_tx.send(false);
52 }
53
54 #[inline]
56 pub fn cancel(self) {
57 let _ = self.stop_tx.send(true);
58 }
59}
60
61impl<O> super::JoinHandle<O> for JoinHandle<O> {
62 type JoinError = JoinError;
63
64 fn detach(self) {
65 Self::detach(self)
66 }
67
68 fn abort(self) {
69 self.cancel();
70 }
71}
72
73impl<O> super::LocalJoinHandle<O> for JoinHandle<O> {
74 type JoinError = JoinError;
75
76 fn detach(self) {
77 Self::detach(self)
78 }
79}
80
81#[derive(Debug, Clone, Copy)]
85pub struct WasmSpawner;
86
87impl AsyncSpawner for WasmSpawner {
88 type JoinHandle<F>
89 = JoinHandle<F>
90 where
91 F: Send + 'static;
92
93 fn spawn<F>(future: F) -> Self::JoinHandle<F::Output>
94 where
95 F::Output: Send + 'static,
96 F: core::future::Future + Send + 'static,
97 {
98 <Self as super::AsyncLocalSpawner>::spawn_local(future)
99 }
100}
101
102impl AsyncLocalSpawner for WasmSpawner {
103 type JoinHandle<F>
104 = JoinHandle<F>
105 where
106 F: 'static;
107
108 fn spawn_local<F>(future: F) -> Self::JoinHandle<F::Output>
109 where
110 F::Output: 'static,
111 F: core::future::Future + 'static,
112 {
113 use futures_util::FutureExt;
114
115 let (tx, rx) = oneshot::channel();
116 let (stop_tx, stop_rx) = oneshot::channel();
117 wasm::spawn_local(async {
118 futures_util::pin_mut!(future);
119
120 futures_util::select! {
121 sig = stop_rx.fuse() => {
122 match sig {
123 Ok(true) => {
124 },
126 Ok(false) | Err(_) => {
127 let _ = future.await;
128 },
129 }
130 },
131 future = (&mut future).fuse() => {
132 let _ = tx.send(future);
133 }
134 }
135 });
136 JoinHandle { stop_tx, rx }
137 }
138}
139
140impl AsyncBlockingSpawner for WasmSpawner {
141 type JoinHandle<R>
142 = JoinHandle<R>
143 where
144 R: Send + 'static;
145
146 fn spawn_blocking<F, R>(_: F) -> Self::JoinHandle<R>
147 where
148 F: FnOnce() -> R + Send + 'static,
149 R: Send + 'static,
150 {
151 panic!("wasm-bindgen-futures does not support blocking tasks")
152 }
153}
154
155impl Yielder for WasmSpawner {
156 async fn yield_now() {
157 YieldNow(false).await
158 }
159
160 async fn yield_now_local() {
161 YieldNow(false).await
162 }
163}
164
165#[derive(Debug)]
167#[must_use = "futures do nothing unless you `.await` or poll them"]
168struct YieldNow(bool);
169
170impl Future for YieldNow {
171 type Output = ();
172
173 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
174 if !self.0 {
175 self.0 = true;
176 cx.waker().wake_by_ref();
177 Poll::Pending
178 } else {
179 Poll::Ready(())
180 }
181 }
182}
183
184#[derive(Debug, Clone, Copy)]
188pub struct WasmRuntime;
189
190impl core::fmt::Display for WasmRuntime {
191 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
192 write!(f, "wasm-bindgen-futures")
193 }
194}
195
196impl super::RuntimeLite for WasmRuntime {
197 type Spawner = WasmSpawner;
198 type LocalSpawner = WasmSpawner;
199 type BlockingSpawner = WasmSpawner;
200
201 cfg_time!(
202 type Instant = Instant;
203 type AfterSpawner = WasmSpawner;
204
205 type Interval = WasmInterval;
206
207 type LocalInterval = WasmInterval;
208
209 type Sleep = WasmSleep;
210
211 type LocalSleep = WasmSleep;
212
213 type Delay<F>
214 = WasmDelay<F>
215 where
216 F: Future + Send;
217
218 type LocalDelay<F>
219 = WasmDelay<F>
220 where
221 F: Future;
222
223 type Timeout<F>
224 = WasmTimeout<F>
225 where
226 F: Future + Send;
227
228 type LocalTimeout<F>
229 = WasmTimeout<F>
230 where
231 F: Future;
232 );
233
234 fn new() -> Self {
235 Self
236 }
237
238 fn name() -> &'static str {
239 "wasm-bindgen-futures"
240 }
241
242 fn fqname() -> &'static str {
243 "wasm-bindgen-futures"
244 }
245
246 fn block_on<F: Future>(_f: F) -> F::Output {
247 panic!("RuntimeLite::block_on is not supported on wasm")
248 }
249
250 async fn yield_now() {
251 YieldNow(false).await
252 }
253
254 cfg_time!(
255 fn interval(interval: Duration) -> Self::Interval {
256 use crate::time::AsyncIntervalExt;
257
258 WasmInterval::interval(interval)
259 }
260
261 fn interval_at(start: Instant, period: Duration) -> Self::Interval {
262 use crate::time::AsyncIntervalExt;
263
264 WasmInterval::interval_at(start, period)
265 }
266
267 fn interval_local(interval: Duration) -> Self::LocalInterval {
268 use crate::time::AsyncIntervalExt;
269
270 WasmInterval::interval(interval)
271 }
272
273 fn interval_local_at(start: Instant, period: Duration) -> Self::LocalInterval {
274 use crate::time::AsyncIntervalExt;
275
276 WasmInterval::interval_at(start, period)
277 }
278
279 fn sleep(duration: Duration) -> Self::Sleep {
280 use crate::time::AsyncSleepExt;
281
282 WasmSleep::sleep(duration)
283 }
284
285 fn sleep_until(instant: Instant) -> Self::Sleep {
286 use crate::time::AsyncSleepExt;
287
288 WasmSleep::sleep_until(instant)
289 }
290
291 fn sleep_local(duration: Duration) -> Self::LocalSleep {
292 use crate::time::AsyncSleepExt;
293
294 WasmSleep::sleep(duration)
295 }
296
297 fn sleep_local_until(instant: Instant) -> Self::LocalSleep {
298 use crate::time::AsyncSleepExt;
299
300 WasmSleep::sleep_until(instant)
301 }
302
303 fn delay<F>(duration: Duration, fut: F) -> Self::Delay<F>
304 where
305 F: Future + Send,
306 {
307 use crate::time::AsyncDelayExt;
308
309 <WasmDelay<F> as AsyncDelayExt<F>>::delay(duration, fut)
310 }
311
312 fn delay_local<F>(duration: Duration, fut: F) -> Self::LocalDelay<F>
313 where
314 F: Future,
315 {
316 use crate::time::AsyncLocalDelayExt;
317
318 <WasmDelay<F> as AsyncLocalDelayExt<F>>::delay(duration, fut)
319 }
320
321 fn delay_at<F>(deadline: Instant, fut: F) -> Self::Delay<F>
322 where
323 F: Future + Send,
324 {
325 use crate::time::AsyncDelayExt;
326
327 <WasmDelay<F> as AsyncDelayExt<F>>::delay_at(deadline, fut)
328 }
329
330 fn delay_local_at<F>(deadline: Instant, fut: F) -> Self::LocalDelay<F>
331 where
332 F: Future,
333 {
334 use crate::time::AsyncLocalDelayExt;
335
336 <WasmDelay<F> as AsyncLocalDelayExt<F>>::delay_at(deadline, fut)
337 }
338
339 fn timeout<F>(duration: Duration, future: F) -> Self::Timeout<F>
340 where
341 F: Future + Send,
342 {
343 use crate::time::AsyncTimeout;
344
345 <WasmTimeout<F> as AsyncTimeout<F>>::timeout(duration, future)
346 }
347
348 fn timeout_at<F>(deadline: Instant, future: F) -> Self::Timeout<F>
349 where
350 F: Future + Send,
351 {
352 use crate::time::AsyncTimeout;
353
354 <WasmTimeout<F> as AsyncTimeout<F>>::timeout_at(deadline, future)
355 }
356
357 fn timeout_local<F>(duration: Duration, future: F) -> Self::LocalTimeout<F>
358 where
359 F: Future,
360 {
361 use crate::time::AsyncLocalTimeout;
362
363 <WasmTimeout<F> as AsyncLocalTimeout<F>>::timeout_local(duration, future)
364 }
365
366 fn timeout_local_at<F>(deadline: Instant, future: F) -> Self::LocalTimeout<F>
367 where
368 F: Future,
369 {
370 use crate::time::AsyncLocalTimeout;
371
372 <WasmTimeout<F> as AsyncLocalTimeout<F>>::timeout_local_at(deadline, future)
373 }
374 );
375}