forked from lightningdevkit/rust-lightning
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathasync_poll.rs
More file actions
132 lines (117 loc) · 4.28 KB
/
async_poll.rs
File metadata and controls
132 lines (117 loc) · 4.28 KB
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
// This file is Copyright its original authors, visible in version control
// history.
//
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
// You may not use this file except in accordance with one or both of these
// licenses.
//! Some utilities to make working with the standard library's [`Future`]s easier
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::future::Future;
use core::marker::Unpin;
use core::pin::Pin;
use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
pub(crate) enum ResultFuture<F: Future<Output = Result<(), E>>, E: Unpin> {
Pending(F),
Ready(Result<(), E>),
}
pub(crate) struct MultiResultFuturePoller<F: Future<Output = Result<(), E>> + Unpin, E: Unpin> {
futures_state: Vec<ResultFuture<F, E>>,
}
impl<F: Future<Output = Result<(), E>> + Unpin, E: Unpin> MultiResultFuturePoller<F, E> {
pub fn new(futures_state: Vec<ResultFuture<F, E>>) -> Self {
Self { futures_state }
}
}
impl<F: Future<Output = Result<(), E>> + Unpin, E: Unpin> Future for MultiResultFuturePoller<F, E> {
type Output = Vec<Result<(), E>>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Vec<Result<(), E>>> {
let mut have_pending_futures = false;
let futures_state = &mut self.get_mut().futures_state;
for state in futures_state.iter_mut() {
match state {
ResultFuture::Pending(ref mut fut) => match Pin::new(fut).poll(cx) {
Poll::Ready(res) => {
*state = ResultFuture::Ready(res);
},
Poll::Pending => {
have_pending_futures = true;
},
},
ResultFuture::Ready(_) => continue,
}
}
if have_pending_futures {
Poll::Pending
} else {
let results = futures_state
.drain(..)
.filter_map(|e| match e {
ResultFuture::Ready(res) => Some(res),
ResultFuture::Pending(_) => {
debug_assert!(
false,
"All futures are expected to be ready if none are pending"
);
None
},
})
.collect();
Poll::Ready(results)
}
}
}
// If we want to poll a future without an async context to figure out if it has completed or
// not without awaiting, we need a Waker, which needs a vtable...we fill it with dummy values
// but sadly there's a good bit of boilerplate here.
//
// Waker::noop() would be preferable, but requires an MSRV of 1.85.
fn dummy_waker_clone(_: *const ()) -> RawWaker {
RawWaker::new(core::ptr::null(), &DUMMY_WAKER_VTABLE)
}
fn dummy_waker_action(_: *const ()) {}
const DUMMY_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
dummy_waker_clone,
dummy_waker_action,
dummy_waker_action,
dummy_waker_action,
);
pub(crate) fn dummy_waker() -> Waker {
unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &DUMMY_WAKER_VTABLE)) }
}
#[cfg(feature = "std")]
/// A type alias for a future that returns a result of type `T` or error `E`.
///
/// This is not exported to bindings users as async is only supported in Rust.
pub type AsyncResult<'a, T, E> = Pin<Box<dyn Future<Output = Result<T, E>> + 'a + Send>>;
#[cfg(not(feature = "std"))]
/// A type alias for a future that returns a result of type `T` or error `E`.
///
/// This is not exported to bindings users as async is only supported in Rust.
pub type AsyncResult<'a, T, E> = Pin<Box<dyn Future<Output = Result<T, E>> + 'a>>;
/// Marker trait to optionally implement `Sync` under std.
///
/// This is not exported to bindings users as async is only supported in Rust.
#[cfg(feature = "std")]
pub use core::marker::Sync as MaybeSync;
#[cfg(not(feature = "std"))]
/// Marker trait to optionally implement `Sync` under std.
///
/// This is not exported to bindings users as async is only supported in Rust.
pub trait MaybeSync {}
#[cfg(not(feature = "std"))]
impl<T> MaybeSync for T where T: ?Sized {}
/// Marker trait to optionally implement `Send` under std.
///
/// This is not exported to bindings users as async is only supported in Rust.
#[cfg(feature = "std")]
pub use core::marker::Send as MaybeSend;
#[cfg(not(feature = "std"))]
/// Marker trait to optionally implement `Send` under std.
///
/// This is not exported to bindings users as async is only supported in Rust.
pub trait MaybeSend {}
#[cfg(not(feature = "std"))]
impl<T> MaybeSend for T where T: ?Sized {}