diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2021-01-27 21:53:54 +0100 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2021-01-27 21:53:54 +0100 |
commit | 30a39f40258b75ee771ca447b3ac3dbe55d70b11 (patch) | |
tree | ee7d84ba3d92d0299ec2dc3920ccb4ff6a3b636d /src | |
parent | acd9f744d2252a13c8b9e34a663497d7284e96a0 (diff) | |
download | rebel-30a39f40258b75ee771ca447b3ac3dbe55d70b11.tar rebel-30a39f40258b75ee771ca447b3ac3dbe55d70b11.zip |
Add "executor"
Diffstat (limited to 'src')
-rw-r--r-- | src/executor.rs | 80 | ||||
-rw-r--r-- | src/main.rs | 15 | ||||
-rw-r--r-- | src/resolve.rs | 5 | ||||
-rw-r--r-- | src/types.rs | 2 |
4 files changed, 87 insertions, 15 deletions
diff --git a/src/executor.rs b/src/executor.rs new file mode 100644 index 0000000..0568cf1 --- /dev/null +++ b/src/executor.rs @@ -0,0 +1,80 @@ +use std::collections::{HashMap, HashSet}; + +use crate::types::*; + +#[derive(Debug)] +pub struct Executor<'a> { + tasks: &'a TaskMap, + tasks_blocked: HashSet<TaskRef>, + tasks_runnable: Vec<TaskRef>, + tasks_done: HashSet<TaskRef>, + rdeps: HashMap<TaskRef, Vec<TaskRef>>, +} + +impl<'a> Executor<'a> { + pub fn new(tasks: &'a TaskMap, taskset: HashSet<TaskRef>) -> Self { + let mut exc = Executor { + tasks, + tasks_blocked: HashSet::new(), + tasks_runnable: Vec::new(), + tasks_done: HashSet::new(), + rdeps: HashMap::new(), + }; + + for task in taskset { + let task_def = tasks.get(&task).expect("Invalid TaskRef"); + if task_def.depends.is_empty() { + exc.tasks_runnable.push(task); + } else { + for dep in &task_def.depends { + let rdep = exc.rdeps.entry(dep.clone()).or_default(); + rdep.push(task.clone()); + } + + exc.tasks_blocked.insert(task); + } + } + + exc + } + + fn deps_satisfied(&self, task: &TaskRef) -> bool { + let task_def = self.tasks.get(task).expect("Invalid TaskRef"); + + for dep in &task_def.depends { + if !self.tasks_done.contains(dep) { + return false; + } + } + + true + } + + fn run_one(&mut self) { + let task = self.tasks_runnable.pop().expect("No runnable tasks left"); + println!("Running {}", task); + println!("Running {} done.", task); + + let rdeps = self.rdeps.get(&task); + + self.tasks_done.insert(task); + + for rdep in rdeps.unwrap_or(&Vec::new()) { + if !self.tasks_blocked.contains(rdep) { + continue; + } + if self.deps_satisfied(rdep) { + self.tasks_blocked.remove(rdep); + self.tasks_runnable.push(rdep.clone()); + } + } + } + + pub fn run(&mut self) { + while !self.tasks_runnable.is_empty() { + self.run_one(); + } + + assert!(self.tasks_blocked.is_empty(), "No runnable tasks left"); + } +} diff --git a/src/main.rs b/src/main.rs index 43221cc..4ebb2bd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ -use std::collections::HashSet; use std::path::Path; +mod executor; mod recipe; mod resolve; mod types; @@ -28,15 +28,6 @@ fn main() { std::process::exit(1); } let taskset = rsv.to_taskset(); - - let (runnable, queued): (HashSet<TaskRef>, HashSet<TaskRef>) = taskset - .into_iter() - .partition(|id| tasks.get(id).unwrap().depends.is_empty()); - - for t in &runnable { - println!("Runnable: {} ({:?})", t, tasks.get(t).unwrap().run); - } - for t in &queued { - println!("Queued: {} ({:?})", t, tasks.get(t).unwrap().run); - } + let mut executor = executor::Executor::new(&tasks, taskset); + executor.run(); } diff --git a/src/resolve.rs b/src/resolve.rs index b386590..9aa26a6 100644 --- a/src/resolve.rs +++ b/src/resolve.rs @@ -51,12 +51,13 @@ impl fmt::Display for Error { impl std::error::Error for Error {} -#[derive(PartialEq)] +#[derive(Debug, PartialEq)] enum ResolveState { Resolving, Resolved, } +#[derive(Debug)] pub struct Resolver<'a> { tasks: &'a TaskMap, resolve_state: HashMap<TaskRef, ResolveState>, @@ -65,7 +66,7 @@ pub struct Resolver<'a> { impl<'a> Resolver<'a> { pub fn new(tasks: &'a TaskMap) -> Self { Resolver { - tasks: tasks, + tasks, resolve_state: HashMap::new(), } } diff --git a/src/types.rs b/src/types.rs index cb777f7..435f21f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -10,7 +10,7 @@ pub struct Task { pub run: String, } -#[derive(Default)] +#[derive(Debug, Default)] pub struct TaskMap(pub HashMap<String, Task>); impl TaskMap { |