1use std::future::Future;
4use std::time::Duration;
5
6pub fn spawn<T>(future: T)
8where T: Future + Send + 'static, T::Output: Send + 'static,
9{
10 #[cfg(feature = "tokio")]
11 if tokio::runtime::Handle::try_current().is_ok() {
12 tokio::spawn(future);
13 } else {
14 std::thread::Builder::new()
15 .spawn(move || {
16 let rt = tokio::runtime::Builder::new_current_thread()
17 .enable_all()
18 .build()
19 .unwrap();
20 rt.block_on(future);
21 })
22 .expect("failed to spawn thread");
23 }
24
25 #[cfg(feature = "async-std")]
26 std::thread::Builder::new()
27 .spawn(move || {
28 async_std::task::block_on(future);
29 })
30 .expect("failed to spawn thread");
31}
32
33pub fn block_on<F>(mut task: F)
35where F: FnMut() -> () + 'static + Send,
36{
37 #[cfg(feature = "tokio")]
38 if tokio::runtime::Handle::try_current().is_ok() {
39 tokio::task::spawn_blocking(move || {
40 task();
41 });
42 return;
43 }
44
45 #[cfg(feature = "async-std")]
46 if async_std::task::try_current().is_some() {
47 std::thread::Builder::new()
48 .spawn(task)
49 .expect("failed to spawn thread");
50 return;
51 }
52
53 task();
54}
55
56#[must_use = "this `Option` should be handled"]
58pub async fn timeout<F>(duration: Duration, future: F) -> Option<F::Output>
59where F: Future
60{
61 #[cfg(feature = "tokio")]
62 return match tokio::time::timeout(duration, future).await {
63 Ok(a) => Some(a),
64 Err(_) => None
65 };
66
67 #[cfg(feature = "async-std")]
68 return match async_std::future::timeout(duration, future).await {
69 Ok(a) => Some(a),
70 Err(_) => None
71 };
72}