tokio/runtime/blocking/
shutdown.rs1use crate::loom::sync::Arc;
7use crate::sync::oneshot;
8
9use std::time::Duration;
10
11#[derive(Debug, Clone)]
12pub(super) struct Sender {
13    _tx: Arc<oneshot::Sender<()>>,
14}
15
16#[derive(Debug)]
17pub(super) struct Receiver {
18    rx: oneshot::Receiver<()>,
19}
20
21pub(super) fn channel() -> (Sender, Receiver) {
22    let (tx, rx) = oneshot::channel();
23    let tx = Sender { _tx: Arc::new(tx) };
24    let rx = Receiver { rx };
25
26    (tx, rx)
27}
28
29impl Receiver {
30    pub(crate) fn wait(&mut self, timeout: Option<Duration>) -> bool {
38        use crate::runtime::context::try_enter_blocking_region;
39
40        if timeout == Some(Duration::from_nanos(0)) {
41            return false;
42        }
43
44        let mut e = match try_enter_blocking_region() {
45            Some(enter) => enter,
46            _ => {
47                if std::thread::panicking() {
48                    return false;
50                } else {
51                    panic!(
52                        "Cannot drop a runtime in a context where blocking is not allowed. \
53                        This happens when a runtime is dropped from within an asynchronous context."
54                    );
55                }
56            }
57        };
58
59        if let Some(timeout) = timeout {
65            e.block_on_timeout(&mut self.rx, timeout).is_ok()
66        } else {
67            let _ = e.block_on(&mut self.rx);
68            true
69        }
70    }
71}