83 lines
2.2 KiB
Rust
83 lines
2.2 KiB
Rust
use iris_core::HasState;
|
|
use std::{
|
|
pin::Pin,
|
|
sync::{
|
|
Arc,
|
|
mpsc::{Receiver as SyncReceiver, Sender as SyncSender, channel as sync_channel},
|
|
},
|
|
};
|
|
use tokio::{
|
|
runtime::Runtime,
|
|
sync::mpsc::{
|
|
UnboundedReceiver as AsyncReceiver, UnboundedSender as AsyncSender,
|
|
unbounded_channel as async_channel,
|
|
},
|
|
};
|
|
use winit::window::Window;
|
|
|
|
pub type TaskMsgSender<Rsc> = SyncSender<Box<dyn TaskUpdate<Rsc>>>;
|
|
pub type TaskMsgReceiver<Rsc> = SyncReceiver<Box<dyn TaskUpdate<Rsc>>>;
|
|
|
|
pub trait TaskUpdate<Rsc: HasState>: FnOnce(&mut Rsc::State, &mut Rsc) + Send {}
|
|
impl<F: FnOnce(&mut Rsc::State, &mut Rsc) + Send, Rsc: HasState> TaskUpdate<Rsc> for F {}
|
|
|
|
pub struct Tasks<Rsc: HasState> {
|
|
start: AsyncSender<BoxTask>,
|
|
window: Arc<Window>,
|
|
msg_send: SyncSender<Box<dyn TaskUpdate<Rsc>>>,
|
|
}
|
|
|
|
pub struct TaskCtx<Rsc: HasState> {
|
|
send: TaskMsgSender<Rsc>,
|
|
}
|
|
|
|
impl<Rsc: HasState> TaskCtx<Rsc> {
|
|
pub fn update(&mut self, f: impl TaskUpdate<Rsc> + 'static) {
|
|
let _ = self.send.send(Box::new(f));
|
|
}
|
|
}
|
|
impl<Rsc: HasState + 'static> TaskCtx<Rsc> {
|
|
fn new(send: TaskMsgSender<Rsc>) -> Self {
|
|
Self { send }
|
|
}
|
|
}
|
|
|
|
type BoxTask = Pin<Box<dyn Future<Output = ()> + Send>>;
|
|
|
|
impl<Rsc: HasState> Tasks<Rsc> {
|
|
pub fn init(window: Arc<Window>) -> (Self, TaskMsgReceiver<Rsc>) {
|
|
let (start, start_recv) = async_channel();
|
|
let (msgs, msgs_recv) = sync_channel();
|
|
std::thread::spawn(|| {
|
|
let rt = Runtime::new().unwrap();
|
|
rt.block_on(listen(start_recv))
|
|
});
|
|
(
|
|
Self {
|
|
start,
|
|
msg_send: msgs,
|
|
window,
|
|
},
|
|
msgs_recv,
|
|
)
|
|
}
|
|
|
|
pub fn spawn<F: AsyncFnOnce(TaskCtx<Rsc>) + 'static + std::marker::Send>(&mut self, task: F)
|
|
where
|
|
F::CallOnceFuture: Send,
|
|
{
|
|
let send = self.msg_send.clone();
|
|
let window = self.window.clone();
|
|
let _ = self.start.send(Box::pin(async move {
|
|
task(TaskCtx::new(send)).await;
|
|
window.request_redraw();
|
|
}));
|
|
}
|
|
}
|
|
|
|
async fn listen(mut recv: AsyncReceiver<BoxTask>) {
|
|
while let Some(task) = recv.recv().await {
|
|
tokio::spawn(task);
|
|
}
|
|
}
|