Skip to main content

leodos_libcfs/runtime/
select_either.rs

1//! A simple implementation of `select` for futures.
2
3use core::future;
4use core::future::Future;
5use core::task::Context;
6use core::task::Poll;
7
8use pin_utils::pin_mut;
9
10/// An enum returned by `select` to indicate which future completed.
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum Either<A, B> {
13    /// The first future completed.
14    Left(A),
15    /// The second future completed.
16    Right(B),
17}
18
19/// Waits for either of two futures to complete.
20///
21/// This function polls both futures concurrently and returns the result of the
22/// first one that finishes. The future that did not complete is dropped.
23pub async fn select_either<'a, F1, F2>(future1: F1, future2: F2) -> Either<F1::Output, F2::Output>
24where
25    F1: Future + 'a,
26    F2: Future + 'a,
27{
28    // Pin both futures to the stack.
29    pin_mut!(future1);
30    pin_mut!(future2);
31
32    future::poll_fn(|cx: &mut Context<'_>| {
33        if let Poll::Ready(output) = future1.as_mut().poll(cx) {
34            return Poll::Ready(Either::Left(output));
35        }
36
37        if let Poll::Ready(output) = future2.as_mut().poll(cx) {
38            return Poll::Ready(Either::Right(output));
39        }
40
41        Poll::Pending
42    })
43    .await
44}