relm4/channel/shutdown/
attached.rs

1// Copyright 2022 System76 <info@system76.com>
2// SPDX-License-Identifier: MIT or Apache-2.0
3
4use super::ShutdownReceiver;
5use futures::future::Either;
6use std::future::Future;
7
8/// A future attached to a shutdown receiver.
9#[derive(Debug)]
10pub struct AttachedShutdown<F> {
11    pub(super) receiver: ShutdownReceiver,
12    pub(super) future: F,
13}
14
15impl<F, Out> AttachedShutdown<F>
16where
17    F: Future<Output = Out>,
18{
19    /// Creates a future which will resolve to this on shutdown.
20    pub async fn on_shutdown<S>(self, shutdown: S) -> Out
21    where
22        S: Future<Output = Out>,
23    {
24        match self.wait().await {
25            Either::Left(_) => shutdown.await,
26            Either::Right(out) => out,
27        }
28    }
29
30    /// Waits until a shutdown signal is received.
31    ///
32    /// - `Either::Left(())` on cancellation.
33    /// - `Either::Right(Out)` on registered future completion.
34    pub async fn wait(self) -> Either<(), Out> {
35        let Self { receiver, future } = self;
36
37        let cancel = receiver.wait();
38        futures::pin_mut!(cancel);
39        futures::pin_mut!(future);
40
41        match futures::future::select(cancel, future).await {
42            Either::Left(_) => Either::Left(()),
43            Either::Right((out, _)) => Either::Right(out),
44        }
45    }
46
47    /// Waits until a shutdown signal is received.
48    ///
49    /// Ignores any output when we don't care about it.
50    pub async fn drop_on_shutdown(self) {
51        let _ = self.wait().await;
52    }
53}