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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
//! Waiting on a future from a thread, a waker that does nothing, and a waker
//! that sets a flag.
//!
//! This module is gated by the `std` cargo feature, the one feature of this
//! crate that links the standard library. It is for three 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`.
//! - **A frame loop that polls again when the future asks for it.** A future
//! that does a bounded amount of work per poll and wakes itself when work is
//! left — the generated `Serve` takes at most 32 claims per poll — makes
//! progress under [`noop_waker`] only at the loop's next frame, because that
//! wake is discarded. [`flag_waker`] records the wake in a flag the loop
//! reads: poll, then poll again while the flag was set, up to the loop's own
//! limit of polls per frame.
//!
//! All three 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`] or [`flag_waker`] and never
//! calls [`block_on`]. A `no_std` frame loop, where this module does not
//! exist, writes the same small waker over `alloc::task::Wake` on an `Arc`
//! when it has an allocator; one without an allocator needs a hand-written
//! `RawWaker`, which needs `unsafe`, as the paragraph above explains.
//!
//! 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 ;
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());
/// ```
/// A waker whose wake sets a flag, and the handle that reads and clears it.
;
/// The read side of a [`flag_waker`]: whether the waker was woken since the
/// last [`take`](WakeFlag::take).
;
/// A waker whose wake sets a flag, for a frame loop that polls again in the
/// same frame when the future asks for it.
///
/// The flag starts clear. A wake of the waker or of any clone of it, by value
/// or by reference, from any thread, sets it; [`WakeFlag::take`] reads and
/// clears it. Nothing is polled by the wake itself. The waker is built as
/// `Waker::from(Arc<Flag>)`, so each call allocates one `Arc`, which the
/// waker and the flag share: create the pair once per loop.
///
/// The frame-loop pattern: poll, then poll again while the flag was set, up to
/// the loop's own limit of polls per frame, so that a future that wakes itself
/// on every poll cannot hold the frame. A wake that arrived between two frames
/// leaves the flag set, which costs at most one extra poll in the next frame.
///
/// ```
/// use std::future::Future;
/// use std::task::Context;
///
/// const POLLS_PER_FRAME: usize = 8;
///
/// let (waker, woken) = ridl_rt::task::flag_waker();
/// let mut cx = Context::from_waker(&waker);
/// let mut fut = std::pin::pin!(std::future::ready(1));
///
/// // One frame.
/// for _ in 0..POLLS_PER_FRAME {
/// if fut.as_mut().poll(&mut cx).is_ready() || !woken.take() {
/// break;
/// }
/// }
///
/// waker.wake_by_ref();
/// assert!(woken.take());
/// assert!(!woken.take());
/// ```