use bevy::tasks::IoTaskPool;
use bevy::tasks::Task;
pub use futures::future::try_join_all;
use futures_lite::future::YieldNow;
use std::pin::Pin;
use std::time::Duration;
use crate::prelude::*;
pub fn block_on<F: Future>(fut: F) -> F::Output {
futures::executor::block_on(fut)
}
pub fn yield_now() -> YieldNow { futures_lite::future::yield_now() }
pub type SendBoxedFuture<T> = Pin<Box<dyn 'static + Send + Future<Output = T>>>;
pub type LifetimeSendBoxedFuture<'a, T> =
Pin<Box<dyn 'a + Send + Future<Output = T>>>;
#[cfg(target_arch = "wasm32")]
pub type MaybeSendBoxedFuture<'a, T> = Pin<Box<dyn 'a + Future<Output = T>>>;
#[cfg(not(target_arch = "wasm32"))]
pub type MaybeSendBoxedFuture<'a, T> =
Pin<Box<dyn 'a + Send + Future<Output = T>>>;
pub fn spawn_local<F>(fut: F) -> Task<F::Output>
where
F: Future + 'static,
F::Output: 'static + MaybeSend + MaybeSync,
{
IoTaskPool::get().spawn_local(fut)
}
pub fn spawn<F>(fut: F) -> Task<F::Output>
where
F: Future + 'static + MaybeSend + MaybeSync,
F::Output: 'static + MaybeSend + MaybeSync,
{
IoTaskPool::get().spawn(fut)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TimeoutError;
impl std::fmt::Display for TimeoutError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "operation timed out")
}
}
impl std::error::Error for TimeoutError {}
pub async fn timeout<F: Future>(
duration: Duration,
fut: F,
) -> Result<F::Output, TimeoutError> {
use futures_lite::future::race;
race(
async move {
time_ext::sleep(duration).await;
Err(TimeoutError)
},
async move { Ok(fut.await) },
)
.await
}
#[cfg(test)]
mod test {
use crate::prelude::*;
#[crate::test]
async fn timeout_completes_before_timeout() {
async_ext::timeout(Duration::from_millis(500), async {
time_ext::sleep(Duration::from_millis(10)).await;
42
})
.await
.unwrap()
.xpect_eq(42);
}
#[crate::test]
async fn timeout_exceeds_timeout() {
async_ext::timeout(Duration::from_millis(10), async {
time_ext::sleep(Duration::from_millis(1000)).await;
42
})
.await
.unwrap_err()
.xpect_eq(async_ext::TimeoutError);
}
}