make the dep-graph not generic

Being generic over the keys made code harder to read.
This commit is contained in:
Niko Matsakis 2021-10-27 08:14:57 -04:00
parent da188fe609
commit e870d02da1
2 changed files with 60 additions and 56 deletions

View file

@ -470,7 +470,7 @@ struct SharedState {
/// The dependency graph tracks which runtimes are blocked on one /// The dependency graph tracks which runtimes are blocked on one
/// another, waiting for queries to terminate. /// another, waiting for queries to terminate.
dependency_graph: Mutex<DependencyGraph<DatabaseKeyIndex>>, dependency_graph: Mutex<DependencyGraph>,
} }
impl SharedState { impl SharedState {
@ -636,34 +636,3 @@ impl Drop for RevisionGuard {
} }
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dependency_graph_path1() {
let mut graph = DependencyGraph::default();
let a = RuntimeId { counter: 0 };
let b = RuntimeId { counter: 1 };
assert!(graph.add_edge(a, 2, b, vec![1]));
// assert!(graph.add_edge(b, &1, a, vec![3, 2]));
let mut v = vec![];
graph.push_cycle_path(1, a, vec![3, 2], &mut v);
assert_eq!(v, vec![1, 2]);
}
#[test]
fn dependency_graph_path2() {
let mut graph = DependencyGraph::default();
let a = RuntimeId { counter: 0 };
let b = RuntimeId { counter: 1 };
let c = RuntimeId { counter: 2 };
assert!(graph.add_edge(a, 3, b, vec![1]));
assert!(graph.add_edge(b, 4, c, vec![2, 3]));
// assert!(graph.add_edge(c, &1, a, vec![5, 6, 4, 7]));
let mut v = vec![];
graph.push_cycle_path(1, a, vec![5, 6, 4, 7], &mut v);
assert_eq!(v, vec![1, 3, 4, 7]);
}
}

View file

@ -1,28 +1,24 @@
use crate::RuntimeId; use crate::{DatabaseKeyIndex, RuntimeId};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::hash::Hash;
#[derive(Debug)] #[derive(Debug)]
pub(super) struct DependencyGraph<K: Hash + Eq> { pub(super) struct DependencyGraph {
/// A `(K -> V)` pair in this map indicates that the the runtime /// A `(K -> V)` pair in this map indicates that the the runtime
/// `K` is blocked on some query executing in the runtime `V`. /// `K` is blocked on some query executing in the runtime `V`.
/// This encodes a graph that must be acyclic (or else deadlock /// This encodes a graph that must be acyclic (or else deadlock
/// will result). /// will result).
edges: FxHashMap<RuntimeId, Edge<K>>, edges: FxHashMap<RuntimeId, Edge>,
labels: FxHashMap<K, SmallVec<[RuntimeId; 4]>>, labels: FxHashMap<DatabaseKeyIndex, SmallVec<[RuntimeId; 4]>>,
} }
#[derive(Debug)] #[derive(Debug)]
struct Edge<K> { struct Edge {
id: RuntimeId, id: RuntimeId,
path: Vec<K>, path: Vec<DatabaseKeyIndex>,
} }
impl<K> Default for DependencyGraph<K> impl Default for DependencyGraph {
where
K: Hash + Eq,
{
fn default() -> Self { fn default() -> Self {
DependencyGraph { DependencyGraph {
edges: Default::default(), edges: Default::default(),
@ -31,17 +27,14 @@ where
} }
} }
impl<K> DependencyGraph<K> impl DependencyGraph {
where
K: Hash + Eq + Clone,
{
/// Attempt to add an edge `from_id -> to_id` into the result graph. /// Attempt to add an edge `from_id -> to_id` into the result graph.
pub(super) fn add_edge( pub(super) fn add_edge(
&mut self, &mut self,
from_id: RuntimeId, from_id: RuntimeId,
database_key: K, database_key: DatabaseKeyIndex,
to_id: RuntimeId, to_id: RuntimeId,
path: impl IntoIterator<Item = K>, path: impl IntoIterator<Item = DatabaseKeyIndex>,
) -> bool { ) -> bool {
assert_ne!(from_id, to_id); assert_ne!(from_id, to_id);
debug_assert!(!self.edges.contains_key(&from_id)); debug_assert!(!self.edges.contains_key(&from_id));
@ -71,7 +64,7 @@ where
true true
} }
pub(super) fn remove_edge(&mut self, database_key: K, to_id: RuntimeId) { pub(super) fn remove_edge(&mut self, database_key: DatabaseKeyIndex, to_id: RuntimeId) {
let vec = self.labels.remove(&database_key).unwrap_or_default(); let vec = self.labels.remove(&database_key).unwrap_or_default();
for from_id in &vec { for from_id in &vec {
@ -82,13 +75,11 @@ where
pub(super) fn push_cycle_path( pub(super) fn push_cycle_path(
&self, &self,
database_key: K, database_key: DatabaseKeyIndex,
to: RuntimeId, to: RuntimeId,
local_path: impl IntoIterator<Item = K>, local_path: impl IntoIterator<Item = DatabaseKeyIndex>,
output: &mut Vec<K>, output: &mut Vec<DatabaseKeyIndex>,
) where ) {
K: std::fmt::Debug,
{
let mut current = Some((to, std::slice::from_ref(&database_key))); let mut current = Some((to, std::slice::from_ref(&database_key)));
let mut last = None; let mut last = None;
let mut local_path = Some(local_path); let mut local_path = Some(local_path);
@ -123,3 +114,47 @@ where
} }
} }
} }
#[cfg(test)]
mod tests {
use super::*;
fn dki(n: u32) -> DatabaseKeyIndex {
DatabaseKeyIndex {
group_index: 0,
query_index: 0,
key_index: n,
}
}
macro_rules! dkivec {
($($n:expr),*) => {
vec![$(dki($n)),*]
}
}
#[test]
fn dependency_graph_path1() {
let mut graph = DependencyGraph::default();
let a = RuntimeId { counter: 0 };
let b = RuntimeId { counter: 1 };
assert!(graph.add_edge(a, dki(2), b, dkivec![1]));
let mut v = vec![];
graph.push_cycle_path(dki(1), a, dkivec![3, 2], &mut v);
assert_eq!(v, vec![dki(1), dki(2)]);
}
#[test]
fn dependency_graph_path2() {
let mut graph = DependencyGraph::default();
let a = RuntimeId { counter: 0 };
let b = RuntimeId { counter: 1 };
let c = RuntimeId { counter: 2 };
assert!(graph.add_edge(a, dki(3), b, dkivec![1]));
assert!(graph.add_edge(b, dki(4), c, dkivec![2, 3]));
// assert!(graph.add_edge(c, &1, a, vec![5, 6, 4, 7]));
let mut v = vec![];
graph.push_cycle_path(dki(1), a, dkivec![5, 6, 4, 7], &mut v);
assert_eq!(v, dkivec![1, 3, 4, 7]);
}
}