1 //! helper data structure to schedule work for parallel prime caches.
2 use std::{collections::VecDeque, hash::Hash};
6 pub(crate) struct TopologicSortIterBuilder<T> {
7 nodes: FxHashMap<T, Entry<T>>,
10 impl<T> TopologicSortIterBuilder<T>
12 T: Copy + Eq + PartialEq + Hash,
15 Self { nodes: Default::default() }
18 fn get_or_create_entry(&mut self, item: T) -> &mut Entry<T> {
19 self.nodes.entry(item).or_default()
22 pub(crate) fn add(&mut self, item: T, predecessors: impl IntoIterator<Item = T>) {
23 let mut num_predecessors = 0;
25 for predecessor in predecessors.into_iter() {
26 self.get_or_create_entry(predecessor).successors.push(item);
27 num_predecessors += 1;
30 let entry = self.get_or_create_entry(item);
31 entry.num_predecessors += num_predecessors;
34 pub(crate) fn build(self) -> TopologicalSortIter<T> {
39 |(item, entry)| if entry.num_predecessors == 0 { Some(*item) } else { None },
43 TopologicalSortIter { nodes: self.nodes, ready }
47 pub(crate) struct TopologicalSortIter<T> {
49 nodes: FxHashMap<T, Entry<T>>,
52 impl<T> TopologicalSortIter<T>
54 T: Copy + Eq + PartialEq + Hash,
56 pub(crate) fn builder() -> TopologicSortIterBuilder<T> {
57 TopologicSortIterBuilder::new()
60 pub(crate) fn pending(&self) -> usize {
64 pub(crate) fn mark_done(&mut self, item: T) {
65 let entry = self.nodes.remove(&item).expect("invariant: unknown item marked as done");
67 for successor in entry.successors {
71 .expect("invariant: unknown successor referenced by entry");
73 succ_entry.num_predecessors -= 1;
74 if succ_entry.num_predecessors == 0 {
75 self.ready.push_back(successor);
81 impl<T> Iterator for TopologicalSortIter<T> {
84 fn next(&mut self) -> Option<Self::Item> {
85 self.ready.pop_front()
91 num_predecessors: usize,
94 impl<T> Default for Entry<T> {
95 fn default() -> Self {
96 Self { successors: Default::default(), num_predecessors: 0 }