@@ -31,8 +31,8 @@ pub struct DependencyQueue<N: Hash + Eq, E: Hash + Eq, V> {
31
31
/// easily indexable with just an `N`
32
32
reverse_dep_map : HashMap < N , HashMap < E , HashSet < N > > > ,
33
33
34
- /// Topological depth of each key
35
- depth : HashMap < N , usize > ,
34
+ /// The total number of packages that are transitively waiting on this package
35
+ priority : HashMap < N , usize > ,
36
36
}
37
37
38
38
impl < N : Hash + Eq , E : Hash + Eq , V > Default for DependencyQueue < N , E , V > {
@@ -47,7 +47,7 @@ impl<N: Hash + Eq, E: Hash + Eq, V> DependencyQueue<N, E, V> {
47
47
DependencyQueue {
48
48
dep_map : HashMap :: new ( ) ,
49
49
reverse_dep_map : HashMap :: new ( ) ,
50
- depth : HashMap :: new ( ) ,
50
+ priority : HashMap :: new ( ) ,
51
51
}
52
52
}
53
53
}
@@ -82,36 +82,39 @@ impl<N: Hash + Eq + Clone, E: Eq + Hash + Clone, V> DependencyQueue<N, E, V> {
82
82
/// All nodes have been added, calculate some internal metadata and prepare
83
83
/// for `dequeue`.
84
84
pub fn queue_finished ( & mut self ) {
85
+ let mut out = HashMap :: new ( ) ;
85
86
for key in self . dep_map . keys ( ) {
86
- depth ( key, & self . reverse_dep_map , & mut self . depth ) ;
87
+ depth ( key, & self . reverse_dep_map , & mut out ) ;
87
88
}
89
+ self . priority = out. into_iter ( ) . map ( |( n, set) | ( n, set. len ( ) ) ) . collect ( ) ;
88
90
89
- fn depth < N : Hash + Eq + Clone , E : Hash + Eq + Clone > (
91
+ fn depth < ' a , N : Hash + Eq + Clone , E : Hash + Eq + Clone > (
90
92
key : & N ,
91
93
map : & HashMap < N , HashMap < E , HashSet < N > > > ,
92
- results : & mut HashMap < N , usize > ,
93
- ) -> usize {
94
- const IN_PROGRESS : usize = !0 ;
95
-
96
- if let Some ( & depth) = results. get ( key) {
97
- assert_ne ! ( depth, IN_PROGRESS , "cycle in DependencyQueue" ) ;
94
+ results : & ' a mut HashMap < N , HashSet < N > > ,
95
+ ) -> & ' a HashSet < N > {
96
+ if results. contains_key ( key) {
97
+ let depth = & results[ key] ;
98
+ assert ! ( !depth. is_empty( ) , "cycle in DependencyQueue" ) ;
98
99
return depth;
99
100
}
101
+ results. insert ( key. clone ( ) , HashSet :: new ( ) ) ;
100
102
101
- results. insert ( key. clone ( ) , IN_PROGRESS ) ;
103
+ let mut set = HashSet :: new ( ) ;
104
+ set. insert ( key. clone ( ) ) ;
102
105
103
- let depth = 1 + map
106
+ for dep in map
104
107
. get ( key)
105
108
. into_iter ( )
106
109
. flat_map ( |it| it. values ( ) )
107
110
. flat_map ( |set| set)
108
- . map ( |dep| depth ( dep, map, results) )
109
- . max ( )
110
- . unwrap_or ( 0 ) ;
111
-
112
- * results. get_mut ( key) . unwrap ( ) = depth;
111
+ {
112
+ set. extend ( depth ( dep, map, results) . iter ( ) . cloned ( ) )
113
+ }
113
114
114
- depth
115
+ let slot = results. get_mut ( key) . unwrap ( ) ;
116
+ * slot = set;
117
+ return & * slot;
115
118
}
116
119
}
117
120
@@ -122,7 +125,7 @@ impl<N: Hash + Eq + Clone, E: Eq + Hash + Clone, V> DependencyQueue<N, E, V> {
122
125
pub fn dequeue ( & mut self ) -> Option < ( N , V ) > {
123
126
// Look at all our crates and find everything that's ready to build (no
124
127
// deps). After we've got that candidate set select the one which has
125
- // the maximum depth in the dependency graph. This way we should
128
+ // the maximum priority in the dependency graph. This way we should
126
129
// hopefully keep CPUs hottest the longest by ensuring that long
127
130
// dependency chains are scheduled early on in the build process and the
128
131
// leafs higher in the tree can fill in the cracks later.
@@ -135,7 +138,7 @@ impl<N: Hash + Eq + Clone, E: Eq + Hash + Clone, V> DependencyQueue<N, E, V> {
135
138
. iter ( )
136
139
. filter ( |( _, ( deps, _) ) | deps. is_empty ( ) )
137
140
. map ( |( key, _) | key. clone ( ) )
138
- . max_by_key ( |k| self . depth [ k] ) ;
141
+ . max_by_key ( |k| self . priority [ k] ) ;
139
142
let key = match next {
140
143
Some ( key) => key,
141
144
None => return None ,
0 commit comments