use alloc::collections::BTreeMap;
use super::id::ProcId;
use super::manager::Manage;
use super::scheduler::Schedule;
use super::ProcRel;
use core::marker::PhantomData;
#[cfg(feature = "proc")]
pub struct PManager<P, MP: Manage<P, ProcId> + Schedule<ProcId>> {
rel_map: BTreeMap<ProcId, ProcRel>,
manager: Option<MP>,
current: Option<ProcId>,
phantom_data: PhantomData<P>,
}
impl<P, MP: Manage<P, ProcId> + Schedule<ProcId>> PManager<P, MP> {
pub const fn new() -> Self {
Self {
rel_map: BTreeMap::new(),
manager: None,
current: None,
phantom_data: PhantomData::<P>,
}
}
pub fn find_next(&mut self) -> Option<&mut P> {
if let Some(id) = self.manager.as_mut().unwrap().fetch() {
if let Some(task) = self.manager.as_mut().unwrap().get_mut(id) {
self.current = Some(id);
Some(task)
} else {
None
}
} else {
None
}
}
pub fn set_manager(&mut self, manager: MP) {
self.manager = Some(manager);
}
pub fn make_current_suspend(&mut self) {
let id = self.current.unwrap();
self.manager.as_mut().unwrap().add(id);
self.current = None;
}
pub fn make_current_exited(&mut self, exit_code: isize) {
let id = self.current.unwrap();
self.manager.as_mut().unwrap().delete(id);
let current_rel = self.rel_map.remove(&id).unwrap();
let parent_pid = current_rel.parent;
let children = current_rel.children;
if let Some(parent_rel) = self.rel_map.get_mut(&parent_pid) {
parent_rel.del_child(id, exit_code);
}
for i in children {
self.rel_map.get_mut(&i).unwrap().parent = ProcId::from_usize(0);
self.rel_map
.get_mut(&ProcId::from_usize(0))
.unwrap()
.add_child(i);
}
self.current = None;
}
pub fn add(&mut self, id: ProcId, task: P, parent: ProcId) {
self.manager.as_mut().unwrap().insert(id, task);
self.manager.as_mut().unwrap().add(id);
if parent.get_usize() != usize::MAX {
let parent_relation = self
.rel_map
.get_mut(&parent)
.expect("Parent process must exist in rel_map");
parent_relation.add_child(id);
}
self.rel_map.insert(id, ProcRel::new(parent));
}
pub fn current(&mut self) -> Option<&mut P> {
let id = self.current.unwrap();
self.manager.as_mut().unwrap().get_mut(id)
}
#[inline]
pub fn get_task(&mut self, id: ProcId) -> Option<&mut P> {
self.manager.as_mut().unwrap().get_mut(id)
}
pub fn wait(&mut self, child_pid: ProcId) -> Option<(ProcId, isize)> {
let id = self.current.unwrap();
let current_rel = self.rel_map.get_mut(&id).unwrap();
if child_pid.get_usize() == usize::MAX {
current_rel.wait_any_child()
} else {
current_rel.wait_child(child_pid)
}
}
}