use std::boxed::Box;
use std::thread;
use crate::{Schedulable, Waitable};
pub struct Pending<F>
where
F: FnOnce() -> (),
F: Send + 'static,
{
op: Option<F>,
}
impl<F> Pending<F>
where
F: FnOnce() -> (),
F: Send + 'static,
{
pub fn new(op: F) -> Self {
Self { op: Some(op) }
}
}
impl<F> Schedulable for Pending<F>
where
F: FnOnce() -> (),
F: Send + 'static,
{
fn start(&mut self) -> Box<dyn Waitable> {
let mut op = None;
std::mem::swap(&mut self.op, &mut op);
if let Some(op) = op {
Box::new(Handle::new(op))
} else {
panic!("Attempt to schdule more than once!");
}
}
}
pub struct Handle<'a> {
handle: Option<thread::JoinHandle<()>>,
err_handler: Option<Box<FnMut() -> () + 'a>>,
}
impl<'a> Handle<'a> {
pub fn new<F>(f: F) -> Self
where
F: FnOnce() -> (),
F: Send + 'static,
{
Self {
handle: Some(thread::spawn(f)),
err_handler: None,
}
}
pub fn with_handler<F>(mut self, f: Box<F>) -> Self
where
F: FnMut() -> (),
F: 'a,
{
self.err_handler = Some(f);
self
}
}
impl<'a> Waitable for Handle<'a> {
fn wait(&mut self) {
let mut handle = None;
std::mem::swap(&mut self.handle, &mut handle);
if let Some(handle) = handle {
if let Err(_) = handle.join() {
if let Some(ref mut f) = self.err_handler {
f()
}
}
}
}
}