stop_token/
deadline.rs

1use core::fmt;
2use std::{
3    error::Error,
4    future::Future,
5    io,
6    pin::Pin,
7    task::{Context, Poll},
8};
9
10use crate::StopToken;
11
12/// An error returned when a future times out.
13#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
14pub struct TimedOutError {
15    _private: (),
16}
17
18impl fmt::Debug for TimedOutError {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        f.debug_struct("TimeoutError").finish()
21    }
22}
23
24impl TimedOutError {
25    pub(crate) fn new() -> Self {
26        Self { _private: () }
27    }
28}
29
30impl Error for TimedOutError {}
31
32impl Into<io::Error> for TimedOutError {
33    fn into(self) -> io::Error {
34        io::Error::new(io::ErrorKind::TimedOut, "Future has timed out")
35    }
36}
37
38impl fmt::Display for TimedOutError {
39    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40        "Future has timed out".fmt(f)
41    }
42}
43
44pin_project_lite::pin_project! {
45    /// A future that times out after a duration of time.
46    #[must_use = "Futures do nothing unless polled or .awaited"]
47    #[derive(Debug)]
48    pub struct Deadline {
49        #[pin]
50        pub(crate) kind: DeadlineKind,
51    }
52}
53
54cfg_if::cfg_if! {
55    if #[cfg(all(feature = "tokio", feature = "async-io"))] {
56        pin_project_lite::pin_project! {
57            #[project = DeadlineKindProj]
58            #[derive(Debug, Clone)]
59            pub(crate) enum DeadlineKind {
60                StopToken{ #[pin]t: StopToken},
61                Tokio{#[pin]t: crate::tokio::Deadline},
62                AsyncIo{#[pin]t: crate::async_io::Deadline},
63            }
64        }
65    } else if #[cfg(feature = "tokio")] {
66        pin_project_lite::pin_project! {
67            #[project = DeadlineKindProj]
68            #[derive(Debug, Clone)]
69            pub(crate) enum DeadlineKind {
70                StopToken{ #[pin]t: StopToken},
71                Tokio{#[pin]t: crate::tokio::Deadline},
72            }
73        }
74    } else if #[cfg(feature = "async-io")] {
75        pin_project_lite::pin_project! {
76            #[project = DeadlineKindProj]
77            #[derive(Debug, Clone)]
78            pub(crate) enum DeadlineKind {
79                StopToken{ #[pin]t: StopToken},
80                AsyncIo{#[pin]t: crate::async_io::Deadline},
81            }
82        }
83    } else {
84        pin_project_lite::pin_project! {
85            #[project = DeadlineKindProj]
86            #[derive(Debug, Clone)]
87            pub(crate) enum DeadlineKind {
88                StopToken{ #[pin]t: StopToken},
89            }
90        }
91    }
92}
93
94impl Clone for Deadline {
95    fn clone(&self) -> Self {
96        Self {
97            kind: self.kind.clone(),
98        }
99    }
100}
101
102impl Future for Deadline {
103    type Output = ();
104
105    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
106        match self.project().kind.project() {
107            DeadlineKindProj::StopToken { t } => t.poll(cx),
108            #[cfg(feature = "tokio")]
109            DeadlineKindProj::Tokio { t } => t.poll(cx),
110            #[cfg(feature = "async-io")]
111            DeadlineKindProj::AsyncIo { t } => t.poll(cx),
112        }
113    }
114}