glib/
future_with_timeout.rs
1use std::{error, fmt};
4
5use futures_util::{
6 future::{self, Either, Future},
7 pin_mut,
8};
9
10#[derive(Clone, Copy, PartialEq, Eq, Debug)]
13pub struct FutureWithTimeoutError;
14
15impl fmt::Display for FutureWithTimeoutError {
16 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
17 f.write_str("The future timed out")
18 }
19}
20
21impl error::Error for FutureWithTimeoutError {}
22
23pub async fn future_with_timeout_with_priority<T>(
28 priority: crate::Priority,
29 timeout: std::time::Duration,
30 fut: impl Future<Output = T>,
31) -> Result<T, FutureWithTimeoutError> {
32 let timeout = crate::timeout_future_with_priority(priority, timeout);
33 pin_mut!(fut);
34
35 match future::select(fut, timeout).await {
36 Either::Left((x, _)) => Ok(x),
37 _ => Err(FutureWithTimeoutError),
38 }
39}
40
41pub async fn future_with_timeout<T>(
46 timeout: std::time::Duration,
47 fut: impl Future<Output = T>,
48) -> Result<T, FutureWithTimeoutError> {
49 future_with_timeout_with_priority(crate::Priority::default(), timeout, fut).await
50}
51
52#[cfg(test)]
53mod tests {
54 use std::time::Duration;
55
56 use futures_util::FutureExt;
57
58 use super::*;
59 use crate::{MainContext, MainLoop};
60
61 #[test]
62 fn test_future_with_timeout() {
63 let c = MainContext::new();
64
65 let fut = future::pending::<()>();
66 let result = c.block_on(future_with_timeout(Duration::from_millis(20), fut));
67 assert_eq!(result, Err(FutureWithTimeoutError));
68
69 let fut = future::ready(());
70 let result = c.block_on(future_with_timeout(Duration::from_millis(20), fut));
71 assert_eq!(result, Ok(()));
72 }
73
74 #[test]
75 fn test_future_with_timeout_send() {
76 let c = MainContext::new();
77 let l = MainLoop::new(Some(&c), false);
78
79 let l_clone = l.clone();
80 let fut = future::pending::<()>();
81 c.spawn(
82 future_with_timeout(Duration::from_millis(20), fut).then(move |result| {
83 l_clone.quit();
84 assert_eq!(result, Err(FutureWithTimeoutError));
85 futures_util::future::ready(())
86 }),
87 );
88
89 l.run();
90
91 let l_clone = l.clone();
92 let fut = future::ready(());
93 c.spawn(
94 future_with_timeout(Duration::from_millis(20), fut).then(move |result| {
95 l_clone.quit();
96 assert_eq!(result, Ok(()));
97 futures_util::future::ready(())
98 }),
99 );
100
101 l.run();
102 }
103}