summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2021-01-27 21:53:54 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2021-01-27 21:53:54 +0100
commit30a39f40258b75ee771ca447b3ac3dbe55d70b11 (patch)
treeee7d84ba3d92d0299ec2dc3920ccb4ff6a3b636d /src
parentacd9f744d2252a13c8b9e34a663497d7284e96a0 (diff)
downloadrebel-30a39f40258b75ee771ca447b3ac3dbe55d70b11.tar
rebel-30a39f40258b75ee771ca447b3ac3dbe55d70b11.zip
Add "executor"
Diffstat (limited to 'src')
-rw-r--r--src/executor.rs80
-rw-r--r--src/main.rs15
-rw-r--r--src/resolve.rs5
-rw-r--r--src/types.rs2
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 {