+6
-99
Cargo.lock
+6
-99
Cargo.lock
···
42
42
]
43
43
44
44
[[package]]
45
-
name = "futures"
46
-
version = "0.3.31"
47
-
source = "registry+https://github.com/rust-lang/crates.io-index"
48
-
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
49
-
dependencies = [
50
-
"futures-channel",
51
-
"futures-core 0.3.31",
52
-
"futures-executor",
53
-
"futures-io",
54
-
"futures-sink",
55
-
"futures-task",
56
-
"futures-util",
57
-
]
58
-
59
-
[[package]]
60
-
name = "futures-channel"
61
-
version = "0.3.31"
62
-
source = "registry+https://github.com/rust-lang/crates.io-index"
63
-
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
64
-
dependencies = [
65
-
"futures-core 0.3.31",
66
-
"futures-sink",
67
-
]
68
-
69
-
[[package]]
70
45
name = "futures-combinators"
71
46
version = "0.0.2"
72
47
dependencies = [
73
-
"futures 0.3.31",
74
48
"futures-compat",
75
-
"futures-core 0.0.2",
49
+
"futures-core",
50
+
"futures-util",
76
51
"lifetime-guard",
77
52
]
78
53
···
80
55
name = "futures-compat"
81
56
version = "0.0.2"
82
57
dependencies = [
83
-
"futures-core 0.0.2",
58
+
"futures-core",
84
59
"lifetime-guard",
85
60
]
86
61
···
89
64
version = "0.0.2"
90
65
91
66
[[package]]
92
-
name = "futures-core"
93
-
version = "0.3.31"
94
-
source = "registry+https://github.com/rust-lang/crates.io-index"
95
-
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
96
-
97
-
[[package]]
98
67
name = "futures-derive"
99
68
version = "0.0.2"
100
69
dependencies = [
···
104
73
]
105
74
106
75
[[package]]
107
-
name = "futures-executor"
108
-
version = "0.3.31"
109
-
source = "registry+https://github.com/rust-lang/crates.io-index"
110
-
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
111
-
dependencies = [
112
-
"futures-core 0.3.31",
113
-
"futures-task",
114
-
"futures-util",
115
-
]
116
-
117
-
[[package]]
118
-
name = "futures-io"
119
-
version = "0.3.31"
120
-
source = "registry+https://github.com/rust-lang/crates.io-index"
121
-
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
122
-
123
-
[[package]]
124
-
name = "futures-macro"
125
-
version = "0.3.31"
126
-
source = "registry+https://github.com/rust-lang/crates.io-index"
127
-
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
128
-
dependencies = [
129
-
"proc-macro2",
130
-
"quote",
131
-
"syn",
132
-
]
133
-
134
-
[[package]]
135
-
name = "futures-sink"
136
-
version = "0.3.31"
137
-
source = "registry+https://github.com/rust-lang/crates.io-index"
138
-
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
139
-
140
-
[[package]]
141
-
name = "futures-task"
142
-
version = "0.3.31"
143
-
source = "registry+https://github.com/rust-lang/crates.io-index"
144
-
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
145
-
146
-
[[package]]
147
76
name = "futures-util"
148
-
version = "0.3.31"
149
-
source = "registry+https://github.com/rust-lang/crates.io-index"
150
-
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
77
+
version = "0.0.2"
151
78
dependencies = [
152
-
"futures-channel",
153
-
"futures-core 0.3.31",
154
-
"futures-io",
155
-
"futures-macro",
156
-
"futures-sink",
157
-
"futures-task",
158
-
"memchr",
159
-
"pin-project-lite",
160
-
"pin-utils",
161
-
"slab",
79
+
"futures-core",
80
+
"lifetime-guard",
162
81
]
163
82
164
83
[[package]]
···
258
177
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
259
178
260
179
[[package]]
261
-
name = "pin-utils"
262
-
version = "0.1.0"
263
-
source = "registry+https://github.com/rust-lang/crates.io-index"
264
-
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
265
-
266
-
[[package]]
267
180
name = "proc-macro2"
268
181
version = "1.0.95"
269
182
source = "registry+https://github.com/rust-lang/crates.io-index"
···
351
264
version = "1.3.0"
352
265
source = "registry+https://github.com/rust-lang/crates.io-index"
353
266
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
354
-
355
-
[[package]]
356
-
name = "slab"
357
-
version = "0.4.11"
358
-
source = "registry+https://github.com/rust-lang/crates.io-index"
359
-
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
360
267
361
268
[[package]]
362
269
name = "smallvec"
+2
-3
Cargo.toml
+2
-3
Cargo.toml
···
1
1
[workspace]
2
2
resolver = "3"
3
-
members = [ "futures", "futures-combinators", "futures-compat", "futures-core", "futures-derive", "lifetime-guard"]
3
+
members = [ "futures", "futures-combinators", "futures-compat", "futures-core", "futures-derive", "futures-util", "lifetime-guard"]
4
4
5
5
[workspace.package]
6
6
version = "0.0.2"
···
17
17
futures-compat = { path = "futures-compat", version = "0.0.2" }
18
18
futures-core = { path = "futures-core", version = "0.0.2" }
19
19
futures-derive = { path = "futures-derive", version = "0.0.2" }
20
+
futures-util = { path = "futures-util", version = "0.0.2" }
20
21
lifetime-guard = { path = "lifetime-guard", version = "0.0.2" }
21
-
# TODO probably vendor in
22
-
futures = "0.3"
+24
-28
futures-combinators/src/join.rs
+24
-28
futures-combinators/src/join.rs
···
137
137
mod tests {
138
138
#![no_std]
139
139
140
-
use futures_core::{Future, Wake};
141
-
use lifetime_guard::guard::ValueGuard;
140
+
use futures_core::Future;
142
141
143
-
use crate::wake::{DummyWaker, local_wake, poll_fn};
142
+
use crate::wake::{dummy_guard, local_wake, poll_fn};
144
143
145
144
use super::*;
146
145
147
146
use std::pin;
148
-
use std::ptr::NonNull;
149
147
150
148
#[test]
151
149
fn counters() {
···
169
167
Poll::Pending
170
168
}
171
169
});
172
-
let guard = pin::pin!(ValueGuard::new(NonNull::new(
173
-
&mut DummyWaker as *mut dyn Wake,
174
-
)));
175
-
let join = (f1, f2).join();
176
-
let mut pinned = pin::pin!(join);
170
+
let guard = pin::pin!(dummy_guard());
171
+
let mut join = pin::pin!((f1, f2).join());
177
172
for _ in 0..4 {
178
-
assert_eq!(pinned.as_mut().poll(guard.as_ref()), Poll::Pending);
173
+
assert_eq!(join.as_mut().poll(guard.as_ref()), Poll::Pending);
179
174
}
180
-
assert_eq!(pinned.poll(guard.as_ref()), Poll::Ready((4, 5)));
175
+
assert_eq!(join.poll(guard.as_ref()), Poll::Ready((4, 5)));
181
176
}
182
177
183
-
// #[test]
184
-
// fn never_wake() {
185
-
// let f1 = poll_fn(|_| Poll::<i32>::Pending);
186
-
// let f2 = poll_fn(|_| Poll::<i32>::Pending);
187
-
// let dummy_waker = noop_wake();
188
-
// let join = (f1, f2).join();
189
-
// for _ in 0..10 {
190
-
// assert_eq!(join.poll(&dummy_waker), Poll::Pending);
191
-
// }
192
-
// }
178
+
#[test]
179
+
fn never_wake() {
180
+
let f1 = poll_fn(|_| Poll::<i32>::Ready(0));
181
+
let f2 = poll_fn(|_| Poll::<i32>::Pending);
182
+
let guard = pin::pin!(dummy_guard());
183
+
let mut join = pin::pin!((f1, f2).join());
184
+
for _ in 0..10 {
185
+
assert_eq!(join.as_mut().poll(guard.as_ref()), Poll::Pending);
186
+
}
187
+
}
193
188
194
-
// #[test]
195
-
// fn basic() {
196
-
// let f1 = poll_fn(|_| Poll::Ready(1));
197
-
// let f2 = poll_fn(|_| Poll::Ready(2));
198
-
// let dummy_waker = noop_wake();
199
-
// assert_eq!(f1.along_with(f2).poll(&dummy_waker), Poll::Ready((1, 2)));
200
-
// }
189
+
#[test]
190
+
fn immediate() {
191
+
let f1 = poll_fn(|_| Poll::Ready(1));
192
+
let f2 = poll_fn(|_| Poll::Ready(2));
193
+
let join = pin::pin!(f1.along_with(f2));
194
+
let guard = pin::pin!(dummy_guard());
195
+
assert_eq!(join.poll(guard.as_ref()), Poll::Ready((1, 2)));
196
+
}
201
197
}
+26
-36
futures-combinators/src/race.rs
+26
-36
futures-combinators/src/race.rs
···
2
2
3
3
use crate::wake::WakeArray;
4
4
use std::pin::Pin;
5
-
use std::task::Context;
6
-
use std::{cell::Cell, task::Poll};
5
+
use std::task::Poll;
7
6
8
7
/// from [futures-concurrency](https://github.com/yoshuawuyts/futures-concurrency/tree/main)
9
8
/// Wait for the first future to complete.
···
142
141
mod tests {
143
142
#![no_std]
144
143
145
-
use std::{pin, ptr::NonNull};
144
+
use std::pin;
146
145
147
-
use futures_core::{Future, Wake};
148
-
use lifetime_guard::guard::ValueGuard;
146
+
use futures_core::Future;
149
147
150
-
use crate::wake::{DummyWaker, local_wake, poll_fn};
148
+
use crate::wake::{dummy_guard, local_wake, poll_fn};
151
149
152
150
use super::*;
153
151
···
173
171
Poll::Pending
174
172
}
175
173
});
176
-
let guard = pin::pin!(ValueGuard::new(NonNull::new(
177
-
&mut DummyWaker as *mut dyn Wake,
178
-
)));
179
-
let join = (f1, f2).race();
180
-
let mut pinned = pin::pin!(join);
181
-
assert_eq!(pinned.as_mut().poll(guard.as_ref()), Poll::Pending);
182
-
assert_eq!(
183
-
pinned.poll(guard.as_ref()),
184
-
Poll::Ready(RaceOutputs2::B(2))
185
-
);
174
+
let guard = pin::pin!(dummy_guard());
175
+
let mut race = pin::pin!((f1, f2).race());
176
+
assert_eq!(race.as_mut().poll(guard.as_ref()), Poll::Pending);
177
+
assert_eq!(race.poll(guard.as_ref()), Poll::Ready(RaceOutputs2::B(2)));
186
178
}
187
179
188
-
// #[test]
189
-
// fn never_wake() {
190
-
// let f1 = poll_fn(|_| Poll::<i32>::Pending);
191
-
// let f2 = poll_fn(|_| Poll::<i32>::Pending);
192
-
// let dummy_waker = noop_wake();
193
-
// let join = (f1, f2).race();
194
-
// for _ in 0..10 {
195
-
// assert_eq!(join.poll(&dummy_waker), Poll::Pending);
196
-
// }
197
-
// }
180
+
#[test]
181
+
fn never_wake() {
182
+
let f1 = poll_fn(|_| Poll::<i32>::Pending);
183
+
let f2 = poll_fn(|_| Poll::<i32>::Pending);
184
+
let mut race = pin::pin!((f1, f2).race());
185
+
let guard = pin::pin!(dummy_guard());
186
+
for _ in 0..10 {
187
+
assert_eq!(race.as_mut().poll(guard.as_ref()), Poll::Pending);
188
+
}
189
+
}
198
190
199
-
// #[test]
200
-
// fn basic() {
201
-
// let f1 = poll_fn(|_| Poll::Ready(1));
202
-
// let f2 = poll_fn(|_| Poll::Ready(2));
203
-
// let dummy_waker = noop_wake();
204
-
// assert_eq!(
205
-
// f1.race_with(f2).poll(&dummy_waker),
206
-
// Poll::Ready(RaceOutputs2::A(1))
207
-
// );
208
-
// }
191
+
#[test]
192
+
fn basic() {
193
+
let f1 = poll_fn(|_| Poll::Ready(1));
194
+
let f2 = poll_fn(|_| Poll::Ready(2));
195
+
let race = pin::pin!(f1.race_with(f2));
196
+
let guard = pin::pin!(dummy_guard());
197
+
assert_eq!(race.poll(guard.as_ref()), Poll::Ready(RaceOutputs2::A(1)));
198
+
}
209
199
}
+4
futures-combinators/src/wake.rs
+4
futures-combinators/src/wake.rs
+57
-30
futures-compat/src/lib.rs
+57
-30
futures-compat/src/lib.rs
···
2
2
//! with an executor/reactor intended for bcsc::Future is strictly unsound.
3
3
4
4
use std::{
5
+
hint::unreachable_unchecked,
5
6
mem::ManuallyDrop,
6
7
pin::Pin,
7
8
ptr::NonNull,
···
11
12
use futures_core::Wake;
12
13
use lifetime_guard::{atomic_guard::AtomicValueGuard, guard::ValueGuard};
13
14
14
-
static EVIL_VTABLE: RawWakerVTable = RawWakerVTable::new(
15
-
|_| panic!("wtf"),
16
-
|_| panic!("wtf"),
17
-
|_| panic!("wtf"),
18
-
|_| panic!("wtf"),
19
-
);
20
-
21
15
pub type WakePtr = Option<NonNull<dyn Wake>>;
16
+
pub type LocalWaker = ValueGuard<WakePtr>;
17
+
pub type AtomicWaker = AtomicValueGuard<WakePtr>;
18
+
19
+
static EVIL_VTABLE: RawWakerVTable = unsafe {
20
+
RawWakerVTable::new(
21
+
|_| unreachable_unchecked(),
22
+
|_| unreachable_unchecked(),
23
+
|_| unreachable_unchecked(),
24
+
|_| unreachable_unchecked(),
25
+
)
26
+
};
22
27
23
28
/// Coerces a pinned `ValueGuard` reference to a `Waker` for use in
24
29
/// `core::future::Future`
25
30
///
26
31
/// Any usage or storage of the resulting `Waker` is undefined behavior.
27
-
pub unsafe fn guard_to_waker(
28
-
guard: Pin<&ValueGuard<WakePtr>>,
29
-
) -> ManuallyDrop<Waker> {
32
+
pub unsafe fn guard_to_waker(guard: Pin<&LocalWaker>) -> ManuallyDrop<Waker> {
30
33
ManuallyDrop::new(unsafe {
31
34
Waker::from_raw(RawWaker::new(
32
35
guard.get_ref() as *const ValueGuard<WakePtr> as *const (),
···
34
37
))
35
38
})
36
39
}
40
+
37
41
pub unsafe fn atomic_guard_to_waker(
38
-
guard: Pin<&AtomicValueGuard<WakePtr>>,
39
-
) -> Waker {
40
-
unsafe {
42
+
guard: Pin<&AtomicWaker>,
43
+
) -> ManuallyDrop<Waker> {
44
+
ManuallyDrop::new(unsafe {
41
45
Waker::from_raw(RawWaker::new(
42
46
guard.get_ref() as *const AtomicValueGuard<WakePtr> as *const (),
43
47
&EVIL_VTABLE,
44
48
))
45
-
}
49
+
})
46
50
}
47
51
48
52
/// Coerces a `Waker` into a pinned `AtomicValueGuard` reference.
49
53
///
50
54
/// This should only be used to undo the work of `guard_to_waker`.
51
-
pub unsafe fn waker_to_guard<'a>(
52
-
waker: &Waker,
53
-
) -> Pin<&'a ValueGuard<WakePtr>> {
55
+
pub unsafe fn waker_to_guard<'a>(waker: &Waker) -> Pin<&LocalWaker> {
54
56
unsafe {
55
57
Pin::new_unchecked(&*(waker.data() as *const ValueGuard<WakePtr>))
56
58
}
57
59
}
58
-
pub unsafe fn waker_to_atomic_guard<'a>(
59
-
waker: &Waker,
60
-
) -> Pin<&'a AtomicValueGuard<WakePtr>> {
60
+
61
+
pub unsafe fn waker_to_atomic_guard<'a>(waker: &Waker) -> Pin<&AtomicWaker> {
61
62
unsafe {
62
63
Pin::new_unchecked(&*(waker.data() as *const AtomicValueGuard<WakePtr>))
63
64
}
64
65
}
65
66
66
-
// TODO should probably return impl futures_core::Future, same for next fn
67
67
pub unsafe fn std_future_to_bespoke<F: core::future::Future>(
68
68
future: F,
69
-
) -> NormalFutureWrapper<F> {
69
+
) -> impl futures_core::Future<LocalWaker, Output = F::Output> {
70
70
NormalFutureWrapper(future)
71
71
}
72
72
73
-
pub unsafe fn bespoke_future_to_std<F: futures_core::Future>(
73
+
pub unsafe fn bespoke_future_to_std<F: futures_core::Future<LocalWaker>>(
74
74
future: F,
75
-
) -> BespokeFutureWrapper<F> {
75
+
) -> impl core::future::Future<Output = F::Output> {
76
76
BespokeFutureWrapper(future)
77
77
}
78
78
···
80
80
#[repr(transparent)]
81
81
pub struct NormalFutureWrapper<F: core::future::Future>(F);
82
82
83
-
impl<F: core::future::Future> futures_core::Future for NormalFutureWrapper<F> {
83
+
impl<F: core::future::Future> futures_core::Future<LocalWaker>
84
+
for NormalFutureWrapper<F>
85
+
{
84
86
type Output = F::Output;
85
87
86
-
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
87
-
unsafe { self.map_unchecked_mut(|this| &mut this.0).poll(cx) }
88
+
fn poll(
89
+
self: Pin<&mut Self>,
90
+
waker: Pin<&LocalWaker>,
91
+
) -> Poll<Self::Output> {
92
+
unsafe {
93
+
self.map_unchecked_mut(|this| &mut this.0)
94
+
.poll(&mut Context::from_waker(&guard_to_waker(waker)))
95
+
}
88
96
}
89
97
}
90
98
91
99
/// wraps custom `bcsc::Future` in impl of `core::future::Future`
92
100
#[repr(transparent)]
93
-
pub struct BespokeFutureWrapper<F: futures_core::Future>(F);
101
+
pub struct BespokeFutureWrapper<F>(F)
102
+
where
103
+
F: futures_core::Future<LocalWaker>;
94
104
95
-
impl<F: futures_core::Future> core::future::Future for BespokeFutureWrapper<F> {
105
+
impl<F> core::future::Future for BespokeFutureWrapper<F>
106
+
where
107
+
F: futures_core::Future<LocalWaker>,
108
+
{
96
109
type Output = F::Output;
97
110
98
111
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
99
-
unsafe { self.map_unchecked_mut(|this| &mut this.0).poll(cx) }
112
+
unsafe {
113
+
self.map_unchecked_mut(|this| &mut this.0)
114
+
.poll(waker_to_guard(cx.waker()))
115
+
}
100
116
}
101
117
}
118
+
119
+
// impl<F> core::future::Future for F
120
+
// where
121
+
// F: for<'a> futures_core::Future<Context<'a>>,
122
+
// {
123
+
// type Output = F::Output;
124
+
125
+
// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
126
+
// self.poll(cx.waker())
127
+
// }
128
+
// }
102
129
103
130
#[cfg(test)]
104
131
mod test {
+43
-12
futures-core/src/lib.rs
+43
-12
futures-core/src/lib.rs
···
1
1
//! Redefinitions of task::Future to be incompatible with them
2
2
3
3
use std::{
4
-
ops,
4
+
ops::{self, DerefMut},
5
5
pin::Pin,
6
-
task::{Context, Poll},
6
+
task::Poll,
7
7
};
8
8
9
9
/// A future represents an asynchronous computation obtained by use of `async`.
···
35
35
message = "`{Self}` is not a `bcsc::Future`",
36
36
note = "If you are trying to await a `core::future::Future` from within a `bcsc::Future`, note that the systems are incompatible."
37
37
)]
38
-
pub trait Future {
38
+
pub trait Future<Waker> {
39
39
/// The type of value produced on completion.
40
40
type Output;
41
41
···
99
99
/// [`Poll::Ready(val)`]: Poll::Ready
100
100
/// [`Waker`]: crate::task::Waker
101
101
/// [`Waker::wake`]: crate::task::Waker::wake
102
-
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
102
+
fn poll(self: Pin<&mut Self>, waker: Pin<&Waker>) -> Poll<Self::Output>;
103
103
}
104
104
105
-
impl<F: ?Sized + Future + Unpin> Future for &mut F {
105
+
impl<Waker, F: ?Sized + Future<Waker> + Unpin> Future<Waker> for &mut F {
106
106
type Output = F::Output;
107
107
108
108
fn poll(
109
109
mut self: Pin<&mut Self>,
110
-
cx: &mut Context<'_>,
110
+
waker: Pin<&Waker>,
111
111
) -> Poll<Self::Output> {
112
-
F::poll(Pin::new(&mut **self), cx)
112
+
F::poll(Pin::new(&mut **self), waker)
113
113
}
114
114
}
115
115
116
-
impl<P> Future for Pin<P>
116
+
impl<Waker, P> Future<Waker> for Pin<P>
117
117
where
118
-
P: ops::DerefMut<Target: Future>,
118
+
P: ops::DerefMut<Target: Future<Waker>>,
119
+
{
120
+
type Output = <<P as ops::Deref>::Target as Future<Waker>>::Output;
121
+
122
+
fn poll(self: Pin<&mut Self>, waker: Pin<&Waker>) -> Poll<Self::Output> {
123
+
<P::Target as Future<Waker>>::poll(self.as_deref_mut(), waker)
124
+
}
125
+
}
126
+
127
+
/// A future which tracks whether or not the underlying future
128
+
/// should no longer be polled.
129
+
///
130
+
/// `is_terminated` will return `true` if a future should no longer be polled.
131
+
/// Usually, this state occurs after `poll` (or `try_poll`) returned
132
+
/// `Poll::Ready`. However, `is_terminated` may also return `true` if a future
133
+
/// has become inactive and can no longer make progress and should be ignored
134
+
/// or dropped rather than being `poll`ed again.
135
+
pub trait FusedFuture<Waker>: Future<Waker> {
136
+
/// Returns `true` if the underlying future should no longer be polled.
137
+
fn is_terminated(&self) -> bool;
138
+
}
139
+
140
+
impl<Waker, F: FusedFuture<Waker> + ?Sized + Unpin> FusedFuture<Waker>
141
+
for &mut F
119
142
{
120
-
type Output = <<P as ops::Deref>::Target as Future>::Output;
143
+
fn is_terminated(&self) -> bool {
144
+
<F as FusedFuture<Waker>>::is_terminated(&**self)
145
+
}
146
+
}
121
147
122
-
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
123
-
<P::Target as Future>::poll(self.as_deref_mut(), cx)
148
+
impl<Waker, P> FusedFuture<Waker> for Pin<P>
149
+
where
150
+
P: DerefMut + Unpin,
151
+
P::Target: FusedFuture<Waker>,
152
+
{
153
+
fn is_terminated(&self) -> bool {
154
+
<P::Target as FusedFuture<Waker>>::is_terminated(&**self)
124
155
}
125
156
}
126
157
+13
futures-util/Cargo.toml
+13
futures-util/Cargo.toml
···
1
+
[package]
2
+
name = "futures-util"
3
+
version.workspace = true
4
+
rust-version.workspace = true
5
+
edition.workspace = true
6
+
license.workspace = true
7
+
authors.workspace = true
8
+
repository.workspace = true
9
+
homepage.workspace = true
10
+
11
+
[dependencies]
12
+
futures-core = { workspace = true }
13
+
lifetime-guard = { workspace = true }
+17
futures-util/src/lib.rs
+17
futures-util/src/lib.rs
···
1
+
use std::ptr::NonNull;
2
+
3
+
use futures_core::{Future, Wake};
4
+
use lifetime_guard::{atomic_guard::AtomicValueGuard, guard::ValueGuard};
5
+
6
+
pub mod maybe_done;
7
+
8
+
pub type WakePtr = Option<NonNull<dyn Wake>>;
9
+
pub type LocalWaker = ValueGuard<WakePtr>;
10
+
pub type AtomicWaker = AtomicValueGuard<WakePtr>;
11
+
12
+
pub(crate) fn assert_future<T, F>(future: F) -> F
13
+
where
14
+
F: Future<LocalWaker, Output = T>,
15
+
{
16
+
future
17
+
}
+112
futures-util/src/maybe_done.rs
+112
futures-util/src/maybe_done.rs
···
1
+
//! Definition of the MaybeDone combinator
2
+
3
+
use futures_core::FusedFuture;
4
+
5
+
use crate::LocalWaker;
6
+
7
+
use super::assert_future;
8
+
use core::mem;
9
+
use core::pin::Pin;
10
+
use futures_core::Future;
11
+
use std::task::Poll;
12
+
use std::task::ready;
13
+
14
+
/// A future that may have completed.
15
+
///
16
+
/// This is created by the [`maybe_done()`] function.
17
+
#[derive(Debug)]
18
+
pub enum MaybeDone<Fut: Future<LocalWaker>> {
19
+
/// A not-yet-completed future
20
+
Future(/* #[pin] */ Fut),
21
+
/// The output of the completed future
22
+
Done(Fut::Output),
23
+
/// The empty variant after the result of a [`MaybeDone`] has been
24
+
/// taken using the [`take_output`](MaybeDone::take_output) method.
25
+
Gone,
26
+
}
27
+
28
+
impl<Fut: Future<LocalWaker> + Unpin> Unpin for MaybeDone<Fut> {}
29
+
30
+
/// Wraps a future into a `MaybeDone`
31
+
///
32
+
/// # Examples
33
+
///
34
+
/// ```
35
+
/// # futures::executor::block_on(async {
36
+
/// use core::pin::pin;
37
+
///
38
+
/// use futures::future;
39
+
///
40
+
/// let future = future::maybe_done(async { 5 });
41
+
/// let mut future = pin!(future);
42
+
/// assert_eq!(future.as_mut().take_output(), None);
43
+
/// let () = future.as_mut().await;
44
+
/// assert_eq!(future.as_mut().take_output(), Some(5));
45
+
/// assert_eq!(future.as_mut().take_output(), None);
46
+
/// # });
47
+
/// ```
48
+
pub fn maybe_done<Fut: Future<LocalWaker>>(future: Fut) -> MaybeDone<Fut> {
49
+
assert_future::<(), _>(MaybeDone::Future(future))
50
+
}
51
+
52
+
impl<Fut: Future<LocalWaker>> MaybeDone<Fut> {
53
+
/// Returns an [`Option`] containing a mutable reference to the output of the future.
54
+
/// The output of this method will be [`Some`] if and only if the inner
55
+
/// future has been completed and [`take_output`](MaybeDone::take_output)
56
+
/// has not yet been called.
57
+
#[inline]
58
+
pub fn output_mut(self: Pin<&mut Self>) -> Option<&mut Fut::Output> {
59
+
unsafe {
60
+
match self.get_unchecked_mut() {
61
+
Self::Done(res) => Some(res),
62
+
_ => None,
63
+
}
64
+
}
65
+
}
66
+
67
+
/// Attempt to take the output of a `MaybeDone` without driving it
68
+
/// towards completion.
69
+
#[inline]
70
+
pub fn take_output(self: Pin<&mut Self>) -> Option<Fut::Output> {
71
+
match &*self {
72
+
Self::Done(_) => {}
73
+
Self::Future(_) | Self::Gone => return None,
74
+
}
75
+
unsafe {
76
+
match mem::replace(self.get_unchecked_mut(), Self::Gone) {
77
+
Self::Done(output) => Some(output),
78
+
_ => unreachable!(),
79
+
}
80
+
}
81
+
}
82
+
}
83
+
84
+
impl<Fut: Future<LocalWaker>> FusedFuture<LocalWaker> for MaybeDone<Fut> {
85
+
fn is_terminated(&self) -> bool {
86
+
match self {
87
+
Self::Future(_) => false,
88
+
Self::Done(_) | Self::Gone => true,
89
+
}
90
+
}
91
+
}
92
+
93
+
impl<Fut: Future<LocalWaker>> Future<LocalWaker> for MaybeDone<Fut> {
94
+
type Output = ();
95
+
96
+
fn poll(
97
+
mut self: Pin<&mut Self>,
98
+
waker: Pin<&LocalWaker>,
99
+
) -> Poll<Self::Output> {
100
+
unsafe {
101
+
match self.as_mut().get_unchecked_mut() {
102
+
Self::Future(f) => {
103
+
let res = ready!(Pin::new_unchecked(f).poll(waker));
104
+
self.set(Self::Done(res));
105
+
}
106
+
Self::Done(_) => {}
107
+
Self::Gone => panic!("MaybeDone polled after value taken"),
108
+
}
109
+
}
110
+
Poll::Ready(())
111
+
}
112
+
}