mirror of
https://github.com/bertptrs/tracing-mutex.git
synced 2025-12-25 20:50:32 +01:00
Reuse dependency orderings in graph
This avoids a potential panic when adding new nodes to the graph, as there is no feasible way to overflow IDs any more.
This commit is contained in:
22
src/graph.rs
22
src/graph.rs
@@ -25,8 +25,9 @@ where
|
|||||||
V: Eq + Hash + Copy,
|
V: Eq + Hash + Copy,
|
||||||
{
|
{
|
||||||
nodes: HashMap<V, Node<V>>,
|
nodes: HashMap<V, Node<V>>,
|
||||||
/// Next topological sort order
|
// Instead of reordering the orders in the graph whenever a node is deleted, we maintain a list
|
||||||
next_ord: Order,
|
// of unused ids that can be handed out later again.
|
||||||
|
unused_order: Vec<Order>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -55,11 +56,17 @@ where
|
|||||||
///
|
///
|
||||||
/// New nodes are appended to the end of the topological order when added.
|
/// New nodes are appended to the end of the topological order when added.
|
||||||
fn add_node(&mut self, n: V) -> (&mut HashSet<V>, &mut HashSet<V>, Order) {
|
fn add_node(&mut self, n: V) -> (&mut HashSet<V>, &mut HashSet<V>, Order) {
|
||||||
let next_ord = &mut self.next_ord;
|
// need to compute next id before the call to entry() to avoid duplicate borrow of nodes
|
||||||
|
let fallback_id = self.nodes.len();
|
||||||
|
|
||||||
let node = self.nodes.entry(n).or_insert_with(|| {
|
let node = self.nodes.entry(n).or_insert_with(|| {
|
||||||
let order = *next_ord;
|
let order = if let Some(id) = self.unused_order.pop() {
|
||||||
*next_ord = next_ord.checked_add(1).expect("Topological order overflow");
|
// Reuse discarded ordering entry
|
||||||
|
id
|
||||||
|
} else {
|
||||||
|
// Allocate new order id
|
||||||
|
fallback_id
|
||||||
|
};
|
||||||
|
|
||||||
Node {
|
Node {
|
||||||
ord: Cell::new(order),
|
ord: Cell::new(order),
|
||||||
@@ -77,8 +84,11 @@ where
|
|||||||
Some(Node {
|
Some(Node {
|
||||||
out_edges,
|
out_edges,
|
||||||
in_edges,
|
in_edges,
|
||||||
..
|
ord,
|
||||||
}) => {
|
}) => {
|
||||||
|
// Return ordering to the pool of unused ones
|
||||||
|
self.unused_order.push(ord.get());
|
||||||
|
|
||||||
out_edges.into_iter().for_each(|m| {
|
out_edges.into_iter().for_each(|m| {
|
||||||
self.nodes.get_mut(&m).unwrap().in_edges.remove(&n);
|
self.nodes.get_mut(&m).unwrap().in_edges.remove(&n);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user