use ferroui_base::rendering::composition::ServerJobTask;
use ferroui_base::threading::{Dispatcher, DispatcherPriority, DispatcherTask, FerroSynchronizationContext};
use std::error::Error;
use std::future::Future;
use std::pin::Pin;
use std::rc::Rc;
use std::task::{Context, Poll};
pub(crate) fn start<T: 'static>(future: impl Future<Output = T> + 'static) -> DispatcherTask<T> {
let context = FerroSynchronizationContext::current().unwrap_or_else(|| {
FerroSynchronizationContext::with_dispatcher(&Dispatcher::current_dispatcher(), DispatcherPriority::NORMAL)
});
context.to_task_scheduler().start_local(future)
}
pub(crate) struct ServerJobTaskFuture<T> {
task: ServerJobTask<T>,
registered: bool,
}
impl<T: Send + 'static> ServerJobTaskFuture<T> {
pub(crate) fn new(task: ServerJobTask<T>) -> Self {
Self { task, registered: false }
}
}
impl<T: Send + 'static> Future for ServerJobTaskFuture<T> {
type Output = Result<(), ferroui_base::rendering::composition::ServerJobError>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.task.is_completed() {
return Poll::Ready(match self.task.exception() {
Some(error) => Err(error),
None => Ok(()),
});
}
if !self.registered {
self.registered = true;
let waker = cx.waker().clone();
self.task.on_completed(move || waker.wake());
}
Poll::Pending
}
}