use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use crate::Line;
use crate::Ctx;
type TaskArgs<S> = (Line, String, Ctx<S>, );
type TaskOutput<S> = Result<S, String>;
pub trait TaskFn<S> = Fn<TaskArgs<S>, Output=TaskOutput<S>> + Send + Sync + 'static;
pub type TaskId = usize;
#[derive(Clone)]
pub struct Task<S> {
inner: Arc<dyn TaskFn<S>>,
}
impl<S> Task<S> {
pub fn new<F>(f: F) -> Self where F: TaskFn<S> {
Self { inner: Arc::new(f) }
}
}
impl<S> FnOnce<TaskArgs<S>> for Task<S> {
type Output = TaskOutput<S>;
extern "rust-call" fn call_once(self, args: TaskArgs<S>) -> Self::Output {
self.inner.as_ref().call_once(args)
}
}
impl<S> FnMut<TaskArgs<S>> for Task<S> {
extern "rust-call" fn call_mut(&mut self, args: TaskArgs<S>) -> Self::Output {
self.inner.as_ref().call_mut(args)
}
}
impl<S> Fn<TaskArgs<S>> for Task<S> {
extern "rust-call" fn call(&self, args: TaskArgs<S>) -> Self::Output {
self.inner.as_ref().call(args)
}
}
#[derive(Clone)]
pub struct TaskMgr<S> {
tasks: HashMap<TaskId, Task<S>>,
deps: HashMap<TaskId, HashSet<TaskId>>,
}
impl<S> TaskMgr<S> {
pub fn new() -> Self {
Self { tasks: HashMap::default(), deps: Default::default() }
}
pub fn get(&self, id: TaskId) -> Option<&Task<S>> {
self.tasks.get(&id)
}
pub fn get_deps(&self, id: TaskId) -> Option<&HashSet<TaskId>> {
self.deps.get(&id)
}
pub fn insert(&mut self, id: TaskId, task: Task<S>) {
self.tasks.insert(id, task);
}
pub fn insert_dep(&mut self, id: TaskId, dep: TaskId) {
let entry = self.deps.entry(id).or_insert_with(|| HashSet::default());
entry.insert(dep);
}
pub fn insert_deps(&mut self, id: TaskId, deps: HashSet<TaskId>) {
let entry = self.deps.entry(id).or_insert_with(|| HashSet::default());
entry.extend(deps);
}
pub fn insert_with_deps(&mut self, id: TaskId, deps: HashSet<TaskId>, task: Task<S>) {
self.deps.insert(id, deps);
self.tasks.insert(id, task);
}
}