use futures03::task::Poll;
use futures03::Future;
use std::pin::Pin;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::task::Context;
use std::thread;
pub struct Futurified<T: Send + 'static, F: FnOnce() -> T + Send + Unpin> {
tx: Sender<T>,
rx: Receiver<T>,
wrapped: Option<F>,
is_running: bool,
}
pub fn wrap<T: Send + 'static, F: FnOnce() -> T + Send + 'static + Unpin>(
wrapped: F,
) -> Futurified<T, F> {
let (tx, rx) = channel();
Futurified {
tx,
rx,
wrapped: Some(wrapped),
is_running: false,
}
}
pub fn wrap_eager<T: Send + 'static, F: FnOnce() -> T + Send + 'static + Unpin>(
wrapped: F,
) -> Futurified<T, F> {
let mut this = wrap(wrapped);
this.run();
this
}
impl<T: Send + 'static, F: FnOnce() -> T + Send + 'static + Unpin> Futurified<T, F> {
fn run(&mut self) {
self.is_running = true;
let tx = self.tx.clone();
let sfn = self.wrapped.take().unwrap();
thread::spawn(move || {
let result = sfn();
if let Err(e) = tx.send(result) {
println!("Error sending result: {}", e)
}
});
}
}
impl<T: Send + 'static, F: FnOnce() -> T + Send + 'static + Unpin> Future for Futurified<T, F> {
type Output = T;
fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
let mut_self = self.get_mut();
if !mut_self.is_running {
mut_self.run();
}
if let Ok(x) = mut_self.rx.try_recv() {
Poll::Ready(x)
} else {
Poll::Pending
}
}
}