use std::sync::Arc;
use super::job::HeapJob;
use super::scheduler::Scheduler;
use super::scope::Scope;
use super::unwind;
pub struct SchedulerSystem {
scheduler: Option<Arc<Scheduler>>,
}
pub type PanicHandler = Fn(Box<::std::any::Any + Send>) + Send + Sync;
impl SchedulerSystem {
pub fn new(
num: u32,
stack_size: Option<usize>,
panic_handler: Option<Box<PanicHandler>>,
) -> Self {
SchedulerSystem {
scheduler: Some(Scheduler::new(num, stack_size, panic_handler)),
}
}
pub fn headless() -> Self {
SchedulerSystem { scheduler: None }
}
pub fn terminate(&self) {
if let Some(ref scheduler) = self.scheduler {
scheduler.terminate_dec();
scheduler.wait_until_terminated();
}
}
pub fn spawn<F>(&self, func: F)
where
F: FnOnce() + Send + 'static,
{
if let Some(ref scheduler) = self.scheduler {
unsafe {
scheduler.terminate_inc();
let job = Box::new(HeapJob::new({
let sched = scheduler.clone();
move || {
match unwind::halt_unwinding(func) {
Ok(()) => {}
Err(err) => {
sched.handle_panic(err);
}
}
sched.terminate_dec(); }
}));
scheduler.inject_or_push(HeapJob::transmute(job));
}
} else {
func();
}
}
pub fn scope<'s, F, R>(&self, func: F) -> R
where
F: for<'r> FnOnce(&'r Scope<'s>) -> R + 's + Send,
R: Send,
{
unsafe {
if let Some(ref scheduler) = self.scheduler {
scheduler.in_worker(|worker, _| {
let scope = Scope::new(Some(scheduler.clone()));
let result = scope.execute(func);
scope.wait_until_completed(worker);
result.unwrap()
})
} else {
Scope::new(None).execute(func).unwrap()
}
}
}
}