use bevy_ecs::prelude::*;
use bevy_tasks::TaskPool;
use std::future::Future;
use std::sync::Mutex;
use std::sync::mpsc;
pub type BoxedCommand = Box<dyn FnOnce(&mut World) + Send>;
pub type CommandSender = mpsc::Sender<BoxedCommand>;
#[derive(Resource)]
pub struct WintfTaskPool {
pool: TaskPool,
sender: mpsc::Sender<BoxedCommand>,
receiver: Mutex<mpsc::Receiver<BoxedCommand>>,
}
impl WintfTaskPool {
pub fn new() -> Self {
let pool = TaskPool::new();
let (sender, receiver) = mpsc::channel();
Self {
pool,
sender,
receiver: Mutex::new(receiver),
}
}
pub fn spawn<F, Fut>(&self, f: F)
where
F: FnOnce(CommandSender) -> Fut + Send + 'static,
Fut: Future<Output = ()> + Send,
{
let tx = self.sender.clone();
self.pool
.spawn(async move {
f(tx).await;
})
.detach();
}
pub fn drain_and_apply(&self, world: &mut World) {
if let Ok(receiver) = self.receiver.lock() {
for cmd in receiver.try_iter() {
cmd(world);
}
}
}
pub fn drain_commands(&self) -> Vec<BoxedCommand> {
if let Ok(receiver) = self.receiver.lock() {
receiver.try_iter().collect()
} else {
Vec::new()
}
}
#[cfg(test)]
pub fn send_command(&self, cmd: BoxedCommand) {
let _ = self.sender.send(cmd);
}
#[cfg(test)]
pub fn is_empty(&self) -> bool {
true
}
}
impl Default for WintfTaskPool {
fn default() -> Self {
Self::new()
}
}