fix deadlock in file.rs

This commit is contained in:
Folkert 2020-11-10 20:15:38 +01:00
parent 3aa6455795
commit 6490956a84

View file

@ -293,7 +293,7 @@ struct ModuleCache<'a> {
sources: MutMap<ModuleId, (PathBuf, &'a str)>, sources: MutMap<ModuleId, (PathBuf, &'a str)>,
} }
fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) -> BuildTask<'a> { fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) -> Vec<BuildTask<'a>> {
// we blindly assume all dependencies are met // we blindly assume all dependencies are met
match state.dependencies.status.get_mut(&(module_id, phase)) { match state.dependencies.status.get_mut(&(module_id, phase)) {
@ -301,11 +301,20 @@ fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) ->
// start this phase! // start this phase!
*current = Status::Pending; *current = Status::Pending;
} }
Some(Status::Pending) | Some(Status::Done) => { Some(Status::Pending) => {
// don't start this task again! // don't start this task again!
todo!(); return vec![];
}
Some(Status::Done) => {
// don't start this task again, but tell those waiting for it they can continue
return state
.dependencies
.notify(module_id, phase)
.into_iter()
.map(|(module_id, phase)| start_phase(module_id, phase, state))
.flatten()
.collect();
} }
None => match phase { None => match phase {
Phase::LoadHeader => { Phase::LoadHeader => {
// this is fine, mark header loading as pending // this is fine, mark header loading as pending
@ -321,6 +330,7 @@ fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) ->
}, },
} }
let task = {
match phase { match phase {
Phase::LoadHeader => { Phase::LoadHeader => {
let dep_name = state let dep_name = state
@ -350,7 +360,8 @@ fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) ->
let deps_by_name = &parsed.deps_by_name; let deps_by_name = &parsed.deps_by_name;
let num_deps = deps_by_name.len(); let num_deps = deps_by_name.len();
let mut dep_idents: MutMap<ModuleId, IdentIds> = IdentIds::exposed_builtins(num_deps); let mut dep_idents: MutMap<ModuleId, IdentIds> =
IdentIds::exposed_builtins(num_deps);
let State { let State {
ident_ids_by_module, ident_ids_by_module,
@ -496,6 +507,9 @@ fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) ->
} }
} }
} }
};
vec![task]
} }
#[derive(Debug)] #[derive(Debug)]
@ -1329,6 +1343,21 @@ where
.unwrap() .unwrap()
} }
fn start_tasks<'a>(
work: MutSet<(ModuleId, Phase)>,
state: &mut State<'a>,
injector: &Injector<BuildTask<'a>>,
worker_listeners: &'a [Sender<WorkerMsg>],
) -> Result<(), LoadingProblem> {
for (module_id, phase) in work {
for task in start_phase(module_id, phase, state) {
enqueue_task(&injector, worker_listeners, task)?
}
}
Ok(())
}
fn update<'a>( fn update<'a>(
mut state: State<'a>, mut state: State<'a>,
msg: Msg<'a>, msg: Msg<'a>,
@ -1384,19 +1413,11 @@ fn update<'a>(
state.module_cache.headers.insert(header.module_id, header); state.module_cache.headers.insert(header.module_id, header);
for (module_id, phase) in work { start_tasks(work, &mut state, &injector, worker_listeners)?;
let task = start_phase(module_id, phase, &mut state);
enqueue_task(&injector, worker_listeners, task)?
}
let work = state.dependencies.notify(home, Phase::LoadHeader); let work = state.dependencies.notify(home, Phase::LoadHeader);
for (module_id, phase) in work { start_tasks(work, &mut state, &injector, worker_listeners)?;
let task = start_phase(module_id, phase, &mut state);
enqueue_task(&injector, worker_listeners, task)?
}
Ok(state) Ok(state)
} }
@ -1412,11 +1433,7 @@ fn update<'a>(
let work = state.dependencies.notify(module_id, Phase::Parse); let work = state.dependencies.notify(module_id, Phase::Parse);
for (module_id, phase) in work { start_tasks(work, &mut state, &injector, worker_listeners)?;
let task = start_phase(module_id, phase, &mut state);
enqueue_task(&injector, worker_listeners, task)?
}
Ok(state) Ok(state)
} }
@ -1452,11 +1469,7 @@ fn update<'a>(
.dependencies .dependencies
.notify(module_id, Phase::CanonicalizeAndConstrain); .notify(module_id, Phase::CanonicalizeAndConstrain);
for (module_id, phase) in work { start_tasks(work, &mut state, &injector, worker_listeners)?;
let task = start_phase(module_id, phase, &mut state);
enqueue_task(&injector, worker_listeners, task)?
}
Ok(state) Ok(state)
} }
@ -1503,11 +1516,7 @@ fn update<'a>(
.notify(module_id, Phase::CanonicalizeAndConstrain), .notify(module_id, Phase::CanonicalizeAndConstrain),
); );
for (module_id, phase) in work { start_tasks(work, &mut state, &injector, worker_listeners)?;
let task = start_phase(module_id, phase, &mut state);
enqueue_task(&injector, worker_listeners, task)?
}
Ok(state) Ok(state)
} }
@ -1594,11 +1603,7 @@ fn update<'a>(
state.constrained_ident_ids.insert(module_id, ident_ids); state.constrained_ident_ids.insert(module_id, ident_ids);
} }
for (module_id, phase) in work { start_tasks(work, &mut state, &injector, worker_listeners)?;
let task = start_phase(module_id, phase, &mut state);
enqueue_task(&injector, worker_listeners, task)?
}
} }
Ok(state) Ok(state)
@ -1646,11 +1651,8 @@ fn update<'a>(
.dependencies .dependencies
.notify(module_id, Phase::FindSpecializations); .notify(module_id, Phase::FindSpecializations);
for (module_id, phase) in work { start_tasks(work, &mut state, &injector, worker_listeners)?;
let task = start_phase(module_id, phase, &mut state);
enqueue_task(&injector, worker_listeners, task)?
}
Ok(state) Ok(state)
} }
MadeSpecializations { MadeSpecializations {
@ -1718,11 +1720,7 @@ fn update<'a>(
// the originally requested module, we're all done! // the originally requested module, we're all done!
return Ok(state); return Ok(state);
} else { } else {
for (module_id, phase) in work { start_tasks(work, &mut state, &injector, worker_listeners)?;
let task = start_phase(module_id, phase, &mut state);
enqueue_task(&injector, worker_listeners, task)?
}
} }
Ok(state) Ok(state)