stop_token/
stop_source.rs

1use core::future::Future;
2use core::pin::Pin;
3use core::task::{Context, Poll};
4
5use async_channel::{bounded, Receiver, Sender};
6use futures_core::stream::Stream;
7
8use crate::Deadline;
9
10enum Never {}
11
12/// `StopSource` produces `StopToken` and cancels all of its tokens on drop.
13///
14/// # Example:
15///
16/// ```ignore
17/// let source = StopSource::new();
18/// let token = source.token();
19/// schedule_some_work(token);
20/// drop(source); // At this point, scheduled work notices that it is canceled.
21/// ```
22#[derive(Debug)]
23pub struct StopSource {
24    /// Solely for `Drop`.
25    _chan: Sender<Never>,
26    stop_token: StopToken,
27}
28
29/// `StopToken` is a future which completes when the associated `StopSource` is dropped.
30#[derive(Debug, Clone)]
31pub struct StopToken {
32    chan: Receiver<Never>,
33}
34
35impl Default for StopSource {
36    fn default() -> StopSource {
37        let (sender, receiver) = bounded::<Never>(1);
38
39        StopSource {
40            _chan: sender,
41            stop_token: StopToken { chan: receiver },
42        }
43    }
44}
45
46impl StopSource {
47    /// Creates a new `StopSource`.
48    pub fn new() -> StopSource {
49        StopSource::default()
50    }
51
52    /// Produces a new `StopToken`, associated with this source.
53    ///
54    /// Once the source is destroyed, `StopToken` future completes.
55    pub fn token(&self) -> StopToken {
56        self.stop_token.clone()
57    }
58}
59
60impl Into<Deadline> for StopToken {
61    fn into(self) -> Deadline {
62        Deadline {
63            kind: crate::deadline::DeadlineKind::StopToken { t: self },
64        }
65    }
66}
67
68impl Future for StopToken {
69    type Output = ();
70
71    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
72        let chan = Pin::new(&mut self.chan);
73        match Stream::poll_next(chan, cx) {
74            Poll::Pending => Poll::Pending,
75            Poll::Ready(Some(never)) => match never {},
76            Poll::Ready(None) => Poll::Ready(()),
77        }
78    }
79}