use std::future::Future;
use async_channel::{bounded, Receiver, TryRecvError};
use bevy_tasks::{Task, TaskPool};
pub(crate) trait SpawnPollableExt {
fn spawn_pollable<F, T>(&self, future: F) -> PollableTask<T>
where
F: Future<Output = T> + Send + 'static,
T: Send + 'static;
}
pub(crate) struct PollableTask<T> {
receiver: Receiver<T>,
_task: Task<()>,
}
impl<T> PollableTask<T> {
pub(crate) fn poll(&self) -> Option<T> {
match self.receiver.try_recv() {
Ok(value) => Some(value),
Err(error) => match error {
TryRecvError::Empty => None,
TryRecvError::Closed => panic!("PoolableTask couldn't receive"),
},
}
}
}
impl SpawnPollableExt for TaskPool {
fn spawn_pollable<F, T>(&self, future: F) -> PollableTask<T>
where
F: Future<Output = T> + Send + 'static,
T: Send + 'static,
{
let (sender, receiver) = bounded(1);
let task = self.spawn(async move {
let result = future.await;
match sender.send(result).await {
Ok(_) => {}
Err(error) => panic! {"Sending result of a task failed: {error}"},
}
});
PollableTask {
receiver,
_task: task,
}
}
}