1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//! Waiting on a future from a thread, and a waker that does nothing.
//!
//! This module is gated by the `std` cargo feature, the one feature of this
//! crate that links the standard library. It is for two callers:
//!
//! - **A blocking client built over an async one.** A client that returns a
//! future is the one source of truth for a call's behaviour; a blocking
//! variant of the same call is [`block_on`] over that future, so the two
//! cannot diverge. The `deadline` bounds the whole wait.
//! - **A frame loop that polls a future once per frame.** Such a loop needs a
//! `Context`, and a `Context` needs a `Waker`, but the loop polls on its own
//! schedule and has no use for a wake. [`noop_waker`] is that waker: created
//! once when the loop starts and cloned into each `Context`.
//!
//! Both are written without `unsafe`, which this crate forbids, over
//! `std::task::Wake` on an `Arc`. That is why the module is under `std`:
//! `Waker::noop()` needs Rust 1.85, above this crate's minimum, and building a
//! `Waker` from a raw vtable needs `unsafe`. The module takes no dependency:
//! the wait is `std::thread::park_timeout`, whose unpark token cannot be lost
//! between a poll and the park that follows it.
//!
//! The feature compiles for `wasm32-unknown-unknown`, because `just wasm-check`
//! requires every feature to, and [`block_on`] is not usable on that target:
//! `Instant::now()` panics there, and a park does not block the thread. A
//! frame loop on wasm polls with [`noop_waker`] and never calls [`block_on`].
//!
//! Nothing here names a port, an interface or a generated type; the module
//! knows only `core::future::Future`.
extern crate std;
use Future;
use pin;
use ;
use Arc;
use Wake;
use ;
use Instant;
/// Wake by unparking the thread that is blocked in [`block_on`].
;
/// A waker whose wake does nothing.
;
/// Run `fut` to completion on the current thread, parking the thread between
/// polls, and give up at `deadline`.
///
/// The future is polled once immediately, then once more after every wake of
/// the waker it was polled with. Between polls the thread is parked, so the
/// wait costs no CPU. The waker unparks the thread through `std::task::Wake`
/// on an `Arc`; an unpark that arrives while the thread is not parked is kept
/// as a token that ends the next park at once, so a wake between a poll and
/// the park that follows it is not lost. A wake that is not from the waker —
/// `Thread::unpark` called by someone else, or a park ending on its own — is
/// harmless: it causes one extra poll, and the wait continues.
///
/// # The deadline
///
/// - `None`: wait until the future is ready, however long that takes.
/// - `Some(deadline)`: return `Some(output)` from the first poll that returns
/// `Ready`, whenever that poll runs — also after a park that ended late —
/// and `None` once a poll returns `Pending` when
/// `Instant::now() >= deadline`. The future is polled at least once even
/// when the deadline has already passed at entry, so a future that is
/// already ready returns `Some` whatever the deadline. On `None`, the future
/// is dropped without another poll.
///
/// The deadline is checked after each `Pending` poll, so `None` can be
/// returned only after a poll, and each park is given at most the time left
/// until the deadline.
///
/// ```
/// use std::time::{Duration, Instant};
///
/// let out = ridl_rt::task::block_on(std::future::ready(7), None);
/// assert_eq!(out, Some(7));
///
/// let pending = std::future::pending::<u8>();
/// let out = ridl_rt::task::block_on(pending, Some(Instant::now() + Duration::from_millis(10)));
/// assert_eq!(out, None);
/// ```
/// A waker whose wake does nothing, for a loop that polls on its own schedule.
///
/// Waking it, by value or by reference, has no effect and never panics; a
/// future polled with it makes progress only when the caller polls it again.
/// The waker is built as `Waker::from(Arc<Noop>)`, so each call allocates one
/// `Arc`: create it once per loop and clone it into each `Context`, rather
/// than calling this function per poll. Two clones of one waker report
/// `will_wake` as `true`; two wakers from two calls do not.
///
/// ```
/// use std::future::Future;
/// use std::task::Context;
///
/// let waker = ridl_rt::task::noop_waker();
/// let mut cx = Context::from_waker(&waker);
/// let mut fut = std::pin::pin!(std::future::ready(1));
/// assert!(fut.as_mut().poll(&mut cx).is_ready());
/// ```