Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Commit ac9b9bf

Browse files
committed
Topologically sort dirty dependencies and create a linear rustc queue
1 parent 1ce92c1 commit ac9b9bf

File tree

1 file changed

+45
-4
lines changed

1 file changed

+45
-4
lines changed

src/build/plan.rs

+45-4
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ impl Plan {
6161
*self = Plan::new();
6262
}
6363

64+
pub fn is_ready(&self) -> bool {
65+
self.compiler_jobs.is_empty() == false
66+
}
67+
6468
/// Cache a given compiler invocation in `ProcessBuilder` for a given
6569
/// `PackageId` and `TargetKind` in `Target`, to be used when processing
6670
/// cached build plan.
@@ -194,6 +198,36 @@ impl Plan {
194198
.collect()
195199
}
196200

201+
/// Returns a topological ordering of a connected DAG of rev deps. The
202+
/// output is a stack of units that can be linearly rebuilt, starting from
203+
/// the last element.
204+
fn topological_sort(&self, dirties: &HashMap<UnitKey, HashSet<UnitKey>>) -> Vec<UnitKey> {
205+
let mut visited: HashSet<UnitKey> = HashSet::new();
206+
let mut output = vec![];
207+
208+
for (k, _) in dirties {
209+
if !visited.contains(&k) {
210+
dfs(k, &self.rev_dep_graph, &mut visited, &mut output);
211+
}
212+
}
213+
214+
return output;
215+
216+
// Process graph depth-first recursively. A node needs to be pushed
217+
// after processing every other before to ensure topological ordering.
218+
fn dfs(unit: &UnitKey, graph: &HashMap<UnitKey, HashSet<UnitKey>>,
219+
visited: &mut HashSet<UnitKey>, output: &mut Vec<UnitKey>) {
220+
if visited.contains(&unit) { return; }
221+
else {
222+
visited.insert(unit.clone());
223+
for neighbour in graph.get(&unit).unwrap() {
224+
dfs(neighbour, graph, visited, output);
225+
}
226+
output.push(unit.clone());
227+
}
228+
}
229+
}
230+
197231
pub fn prepare_work<T: AsRef<Path> + fmt::Debug>(&self, modified: &[T]) -> WorkStatus {
198232
let dirties = self.fetch_dirty_units(modified);
199233
trace!("fetch_dirty_units: for files {:?}, these units are dirty: {:?}", modified, dirties);
@@ -204,10 +238,13 @@ impl Plan {
204238
let graph = self.dirty_rev_dep_graph(&dirties);
205239
trace!("Constructed dirty rev dep graph: {:?}", graph);
206240

207-
// TODO: Then sort topologically the deps
208-
// TODO: Then map those with a ProcessBuilder
241+
let queue = self.topological_sort(&graph);
242+
trace!("Topologically sorted dirty graph: {:?}", queue);
243+
let jobs = queue.iter()
244+
.map(|x| self.compiler_jobs.get(x).unwrap().clone())
245+
.collect();
209246

210-
WorkStatus::Execute(JobQueue { })
247+
WorkStatus::Execute(JobQueue(jobs))
211248
}
212249
}
213250
}
@@ -217,8 +254,12 @@ pub enum WorkStatus {
217254
Execute(JobQueue)
218255
}
219256

220-
pub struct JobQueue {
257+
pub struct JobQueue(Vec<ProcessBuilder>);
221258

259+
impl JobQueue {
260+
pub fn dequeue(&mut self) -> Option<ProcessBuilder> {
261+
self.0.pop()
262+
}
222263
}
223264

224265
fn key_from_unit(unit: &Unit) -> UnitKey {

0 commit comments

Comments
 (0)