Skip to main content

Dag

Struct Dag 

Source
pub struct Dag<N> {
    nodes: Vec<NodeSlot<N>>,
    edges: Vec<EdgeSlot>,
    free_nodes: Vec<u32>,
    free_edges: Vec<u32>,
    live: usize,
    visited: Vec<u32>,
    stamp: u32,
    stack: Vec<u32>,
    plan_stack: Vec<(u32, bool)>,
    order: Vec<u32>,
}
Expand description

A directed acyclic graph whose edges may not close a cycle.

Slots are recycled: removing a node frees its slot, and a later insertion reuses it. Neither the node array nor the walk stamps shrink, so a graph that once held many nodes keeps scanning that many: memory is bounded by the peak number of nodes held at once, not by the number held now.

Fields§

§nodes: Vec<NodeSlot<N>>§edges: Vec<EdgeSlot>§free_nodes: Vec<u32>

Slots holding no node, to be handed out by Dag::insert.

§free_edges: Vec<u32>

Edge slots holding no edge, to be handed out by Dag::add_edge.

§live: usize

How many slots hold a node.

§visited: Vec<u32>

Per-slot stamp of the most recent walk that visited it. A walk takes a fresh stamp rather than clearing this, so a traversal after the array has grown allocates nothing.

§stamp: u32

The stamp visited presently records.

§stack: Vec<u32>

Reused stack of slot indices for the plain depth-first walks.

§plan_stack: Vec<(u32, bool)>

Reused stack for the post-order walk, where a slot is pushed once to be visited and once more — flagged true — to be emitted.

§order: Vec<u32>

Reused list of the slots a plan selected, in the order it selected them.

Implementations§

Source§

impl<N> Dag<N>

Source

pub fn new() -> Self

Create an empty graph.

Source

pub fn len(&self) -> usize

Number of nodes in the graph.

Source

pub fn is_empty(&self) -> bool

Whether the graph holds no nodes.

Source

pub fn insert(&mut self, weight: N) -> NodeId

Add weight as a node and return a handle to it.

Reusing a freed slot bumps its generation, so handles to the node that occupied the slot before stop resolving.

Source

pub fn iter(&self) -> impl Iterator<Item = (NodeId, &N)>

Every live node, as its handle and its weight, in slot order.

Slots are recycled, so the order is by slot rather than by insertion: a node that reused a freed slot appears where that slot is. The walk covers the whole node array, so it costs the peak number of nodes the graph ever held rather than the number it holds now.

Source

pub fn get(&self, id: NodeId) -> Option<&N>

Borrow the weight of the node id names.

Source

pub fn get_mut(&mut self, id: NodeId) -> Option<&mut N>

Mutably borrow the weight of the node id names.

Source

pub fn add_edge(&mut self, from: NodeId, to: NodeId) -> Result<bool, EdgeError>

Record that to depends on from, and report whether this call recorded it.

Refused when either handle does not resolve, when both name the same node, or when the edge would close a cycle. Declaring an existing dependency again is a no-op rather than a second edge, so Dag::dependencies never yields the same node twice; such a repeat returns Ok(false), and only the call that recorded the edge returns Ok(true).

Source

pub fn dependencies(&self, id: NodeId) -> impl Iterator<Item = NodeId> + '_

The nodes id depends on, in unspecified order.

Empty when the handle does not resolve.

Source

pub fn for_each_dependent_mut(&mut self, id: NodeId, f: impl FnMut(&mut N))

Apply f to id and to every node reachable from it by following dependents.

Only the reachable nodes are visited. A handle that does not resolve visits nothing.

Source

pub fn remove_where_drop(&mut self, is_dead: impl Fn(&N) -> bool) -> usize

Remove every node is_dead reports, and return how many were removed.

A node is dropped with the weights of the nodes that depend on it still in place, so a weight whose drop releases something another node was waiting for only shows up on the next call: a caller that has to reach a fixpoint sweeps until this reports 0.

Source

pub fn topological_order(&self) -> Vec<NodeId>

Every node, ordered so that a node always follows the nodes it depends on.

Nodes that do not depend on one another come in an unspecified order. The graph refuses every edge that would close a cycle, so every node is listed.

Source

fn remove(&mut self, id: NodeId) -> Option<N>

Remove the node id names together with every edge touching it, and return its weight.

Internal: callers go through Dag::remove_where_drop, which selects what to remove without needing a handle the caller may no longer hold.

Source

fn resolve(&self, id: NodeId) -> Option<usize>

Resolve a handle to a slot index, or None when it names no node.

A handle names both a slot and the generation it was in, so a handle whose node was removed — and whose slot was perhaps reused — resolves to nothing rather than to the slot’s current occupant.

Source

fn node_id(&self, index: u32) -> NodeId

Build the handle for a live slot, in the generation the slot is in.

Source

fn has_edge(&self, from: usize, to: usize) -> bool

Whether to depends on from, both already resolved to slot indices.

Source

fn incident<'a>( &'a self, id: NodeId, select: impl Fn(&'a NodeSlot<N>) -> &'a Vec<u32>, ) -> impl Iterator<Item = u32> + 'a

The edge list slot selects, or an empty one when id does not resolve.

Source

fn reaches(&mut self, start: usize, target: usize) -> bool

Whether following dependents from start reaches target.

Source

fn plan_dependents(&mut self, root: NodeId)

Fill Dag::order with root and every node reachable from it by following dependents, in dependency order.

The list is built before the caller acts on it, so a weight mutated as the walk proceeds cannot disturb it.

Source

fn next_stamp(&mut self) -> u32

Take a stamp that no mark in visited carries yet, growing the array to cover the nodes if needed.

Trait Implementations§

Source§

impl<N: Debug> Debug for Dag<N>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<N> Default for Dag<N>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<N> Forget for Dag<N>

§

impl<N> Freeze for Dag<N>
where Vec<NodeSlot<N>>: Freeze,

§

impl<N> RefUnwindSafe for Dag<N>

§

impl<N> Send for Dag<N>
where Vec<NodeSlot<N>>: Send,

§

impl<N> Sync for Dag<N>
where Vec<NodeSlot<N>>: Sync,

§

impl<N> Unpin for Dag<N>
where Vec<NodeSlot<N>>: Unpin,

§

impl<N> UnsafeUnpin for Dag<N>

§

impl<N> UnwindSafe for Dag<N>
where Vec<NodeSlot<N>>: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

§

fn simd_from(_simd: S, value: T) -> T

§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

§

fn simd_into(self, simd: S) -> T

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> Upcast<T> for T

§

fn upcast(&self) -> Option<&T>

§

impl<T> WasmNotSend for T
where T: Send,

§

impl<T> WasmNotSendSync for T
where T: WasmNotSend + WasmNotSync,

§

impl<T> WasmNotSync for T
where T: Sync,

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more