lightning/util/
async_poll.rs1use alloc::boxed::Box;
13use alloc::vec::Vec;
14use core::future::Future;
15use core::marker::Unpin;
16use core::pin::Pin;
17use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
18
19pub(crate) enum ResultFuture<F: Future<Output = Result<(), E>>, E: Unpin> {
20 Pending(F),
21 Ready(Result<(), E>),
22}
23
24pub(crate) struct MultiResultFuturePoller<F: Future<Output = Result<(), E>> + Unpin, E: Unpin> {
25 futures_state: Vec<ResultFuture<F, E>>,
26}
27
28impl<F: Future<Output = Result<(), E>> + Unpin, E: Unpin> MultiResultFuturePoller<F, E> {
29 pub fn new(futures_state: Vec<ResultFuture<F, E>>) -> Self {
30 Self { futures_state }
31 }
32}
33
34impl<F: Future<Output = Result<(), E>> + Unpin, E: Unpin> Future for MultiResultFuturePoller<F, E> {
35 type Output = Vec<Result<(), E>>;
36 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Vec<Result<(), E>>> {
37 let mut have_pending_futures = false;
38 let futures_state = &mut self.get_mut().futures_state;
39 for state in futures_state.iter_mut() {
40 match state {
41 ResultFuture::Pending(ref mut fut) => match Pin::new(fut).poll(cx) {
42 Poll::Ready(res) => {
43 *state = ResultFuture::Ready(res);
44 },
45 Poll::Pending => {
46 have_pending_futures = true;
47 },
48 },
49 ResultFuture::Ready(_) => continue,
50 }
51 }
52
53 if have_pending_futures {
54 Poll::Pending
55 } else {
56 let results = futures_state
57 .drain(..)
58 .filter_map(|e| match e {
59 ResultFuture::Ready(res) => Some(res),
60 ResultFuture::Pending(_) => {
61 debug_assert!(
62 false,
63 "All futures are expected to be ready if none are pending"
64 );
65 None
66 },
67 })
68 .collect();
69 Poll::Ready(results)
70 }
71 }
72}
73
74fn dummy_waker_clone(_: *const ()) -> RawWaker {
80 RawWaker::new(core::ptr::null(), &DUMMY_WAKER_VTABLE)
81}
82fn dummy_waker_action(_: *const ()) {}
83
84const DUMMY_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
85 dummy_waker_clone,
86 dummy_waker_action,
87 dummy_waker_action,
88 dummy_waker_action,
89);
90
91pub(crate) fn dummy_waker() -> Waker {
92 unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &DUMMY_WAKER_VTABLE)) }
93}
94
95#[cfg(feature = "std")]
96pub type AsyncResult<'a, T, E> = Pin<Box<dyn Future<Output = Result<T, E>> + 'a + Send>>;
100#[cfg(not(feature = "std"))]
101pub type AsyncResult<'a, T, E> = Pin<Box<dyn Future<Output = Result<T, E>> + 'a>>;
105
106#[cfg(feature = "std")]
110pub use core::marker::Sync as MaybeSync;
111
112#[cfg(not(feature = "std"))]
113pub trait MaybeSync {}
117#[cfg(not(feature = "std"))]
118impl<T> MaybeSync for T where T: ?Sized {}
119
120#[cfg(feature = "std")]
124pub use core::marker::Send as MaybeSend;
125
126#[cfg(not(feature = "std"))]
127pub trait MaybeSend {}
131#[cfg(not(feature = "std"))]
132impl<T> MaybeSend for T where T: ?Sized {}