Split ScheduleGraph::process_configs function (adopted) (#12435)
Adoption of #10617, resolved conflicts with main --------- Co-authored-by: Stepan Koltsov <stepan.koltsov@gmail.com>
This commit is contained in:
parent
1323de7cd7
commit
e9dc270d68
@ -661,6 +661,42 @@ impl ScheduleGraph {
|
|||||||
&self.conflicting_systems
|
&self.conflicting_systems
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn process_config<T: ProcessNodeConfig>(
|
||||||
|
&mut self,
|
||||||
|
config: NodeConfig<T>,
|
||||||
|
collect_nodes: bool,
|
||||||
|
) -> ProcessConfigsResult {
|
||||||
|
ProcessConfigsResult {
|
||||||
|
densely_chained: true,
|
||||||
|
nodes: collect_nodes
|
||||||
|
.then_some(T::process_config(self, config))
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_collective_conditions<T: ProcessNodeConfig>(
|
||||||
|
&mut self,
|
||||||
|
configs: &mut [NodeConfigs<T>],
|
||||||
|
collective_conditions: Vec<BoxedCondition>,
|
||||||
|
) {
|
||||||
|
if !collective_conditions.is_empty() {
|
||||||
|
if let [config] = configs {
|
||||||
|
for condition in collective_conditions {
|
||||||
|
config.run_if_dyn(condition);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let set = self.create_anonymous_set();
|
||||||
|
for config in configs.iter_mut() {
|
||||||
|
config.in_set_inner(set.intern());
|
||||||
|
}
|
||||||
|
let mut set_config = SystemSetConfig::new(set.intern());
|
||||||
|
set_config.conditions.extend(collective_conditions);
|
||||||
|
self.configure_set_inner(set_config).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds the config nodes to the graph.
|
/// Adds the config nodes to the graph.
|
||||||
///
|
///
|
||||||
/// `collect_nodes` controls whether the `NodeId`s of the processed config nodes are stored in the returned [`ProcessConfigsResult`].
|
/// `collect_nodes` controls whether the `NodeId`s of the processed config nodes are stored in the returned [`ProcessConfigsResult`].
|
||||||
@ -676,157 +712,75 @@ impl ScheduleGraph {
|
|||||||
collect_nodes: bool,
|
collect_nodes: bool,
|
||||||
) -> ProcessConfigsResult {
|
) -> ProcessConfigsResult {
|
||||||
match configs {
|
match configs {
|
||||||
NodeConfigs::NodeConfig(config) => {
|
NodeConfigs::NodeConfig(config) => self.process_config(config, collect_nodes),
|
||||||
let node_id = T::process_config(self, config);
|
|
||||||
if collect_nodes {
|
|
||||||
ProcessConfigsResult {
|
|
||||||
densely_chained: true,
|
|
||||||
nodes: vec![node_id],
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ProcessConfigsResult {
|
|
||||||
densely_chained: true,
|
|
||||||
nodes: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NodeConfigs::Configs {
|
NodeConfigs::Configs {
|
||||||
mut configs,
|
mut configs,
|
||||||
collective_conditions,
|
collective_conditions,
|
||||||
chained,
|
chained,
|
||||||
} => {
|
} => {
|
||||||
let more_than_one_entry = configs.len() > 1;
|
self.apply_collective_conditions(&mut configs, collective_conditions);
|
||||||
if !collective_conditions.is_empty() {
|
|
||||||
if more_than_one_entry {
|
let ignore_deferred = matches!(chained, Chain::YesIgnoreDeferred);
|
||||||
let set = self.create_anonymous_set();
|
let chained = matches!(chained, Chain::Yes | Chain::YesIgnoreDeferred);
|
||||||
for config in &mut configs {
|
|
||||||
config.in_set_inner(set.intern());
|
// Densely chained if
|
||||||
}
|
// * chained and all configs in the chain are densely chained, or
|
||||||
let mut set_config = SystemSetConfig::new(set.intern());
|
// * unchained with a single densely chained config
|
||||||
set_config.conditions.extend(collective_conditions);
|
let mut densely_chained = chained || configs.len() == 1;
|
||||||
self.configure_set_inner(set_config).unwrap();
|
let mut configs = configs.into_iter();
|
||||||
} else {
|
let mut nodes = Vec::new();
|
||||||
for condition in collective_conditions {
|
|
||||||
configs[0].run_if_dyn(condition);
|
let Some(first) = configs.next() else {
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut config_iter = configs.into_iter();
|
|
||||||
let mut nodes_in_scope = Vec::new();
|
|
||||||
let mut densely_chained = true;
|
|
||||||
if chained == Chain::Yes || chained == Chain::YesIgnoreDeferred {
|
|
||||||
let Some(prev) = config_iter.next() else {
|
|
||||||
return ProcessConfigsResult {
|
return ProcessConfigsResult {
|
||||||
nodes: Vec::new(),
|
nodes: Vec::new(),
|
||||||
densely_chained: true,
|
densely_chained,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
let mut previous_result = self.process_configs(prev, true);
|
let mut previous_result = self.process_configs(first, collect_nodes || chained);
|
||||||
densely_chained = previous_result.densely_chained;
|
densely_chained &= previous_result.densely_chained;
|
||||||
for current in config_iter {
|
|
||||||
let current_result = self.process_configs(current, true);
|
|
||||||
densely_chained = densely_chained && current_result.densely_chained;
|
|
||||||
match (
|
|
||||||
previous_result.densely_chained,
|
|
||||||
current_result.densely_chained,
|
|
||||||
) {
|
|
||||||
// Both groups are "densely" chained, so we can simplify the graph by only
|
|
||||||
// chaining the last in the previous list to the first in the current list
|
|
||||||
(true, true) => {
|
|
||||||
let last_in_prev = previous_result.nodes.last().unwrap();
|
|
||||||
let first_in_current = current_result.nodes.first().unwrap();
|
|
||||||
self.dependency.graph.add_edge(
|
|
||||||
*last_in_prev,
|
|
||||||
*first_in_current,
|
|
||||||
(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if chained == Chain::YesIgnoreDeferred {
|
for current in configs {
|
||||||
self.no_sync_edges
|
let current_result = self.process_configs(current, collect_nodes || chained);
|
||||||
.insert((*last_in_prev, *first_in_current));
|
densely_chained &= current_result.densely_chained;
|
||||||
}
|
|
||||||
}
|
|
||||||
// The previous group is "densely" chained, so we can simplify the graph by only
|
|
||||||
// chaining the last item from the previous list to every item in the current list
|
|
||||||
(true, false) => {
|
|
||||||
let last_in_prev = previous_result.nodes.last().unwrap();
|
|
||||||
for current_node in ¤t_result.nodes {
|
|
||||||
self.dependency.graph.add_edge(
|
|
||||||
*last_in_prev,
|
|
||||||
*current_node,
|
|
||||||
(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if chained == Chain::YesIgnoreDeferred {
|
if chained {
|
||||||
self.no_sync_edges.insert((*last_in_prev, *current_node));
|
// if the current result is densely chained, we only need to chain the first node
|
||||||
}
|
let current_nodes = if current_result.densely_chained {
|
||||||
}
|
¤t_result.nodes[..1]
|
||||||
}
|
} else {
|
||||||
// The current list is currently "densely" chained, so we can simplify the graph by
|
¤t_result.nodes
|
||||||
// only chaining every item in the previous list to the first item in the current list
|
};
|
||||||
(false, true) => {
|
// if the previous result was densely chained, we only need to chain the last node
|
||||||
let first_in_current = current_result.nodes.first().unwrap();
|
let previous_nodes = if previous_result.densely_chained {
|
||||||
for previous_node in &previous_result.nodes {
|
&previous_result.nodes[previous_result.nodes.len() - 1..]
|
||||||
self.dependency.graph.add_edge(
|
} else {
|
||||||
*previous_node,
|
&previous_result.nodes
|
||||||
*first_in_current,
|
};
|
||||||
(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if chained == Chain::YesIgnoreDeferred {
|
for previous_node in previous_nodes {
|
||||||
self.no_sync_edges
|
for current_node in current_nodes {
|
||||||
.insert((*previous_node, *first_in_current));
|
self.dependency
|
||||||
}
|
.graph
|
||||||
}
|
.add_edge(*previous_node, *current_node, ());
|
||||||
}
|
|
||||||
// Neither of the lists are "densely" chained, so we must chain every item in the first
|
|
||||||
// list to every item in the second list
|
|
||||||
(false, false) => {
|
|
||||||
for previous_node in &previous_result.nodes {
|
|
||||||
for current_node in ¤t_result.nodes {
|
|
||||||
self.dependency.graph.add_edge(
|
|
||||||
*previous_node,
|
|
||||||
*current_node,
|
|
||||||
(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if chained == Chain::YesIgnoreDeferred {
|
if ignore_deferred {
|
||||||
self.no_sync_edges
|
self.no_sync_edges.insert((*previous_node, *current_node));
|
||||||
.insert((*previous_node, *current_node));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if collect_nodes {
|
if collect_nodes {
|
||||||
nodes_in_scope.append(&mut previous_result.nodes);
|
nodes.append(&mut previous_result.nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
previous_result = current_result;
|
previous_result = current_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure the last config's nodes are added
|
|
||||||
if collect_nodes {
|
if collect_nodes {
|
||||||
nodes_in_scope.append(&mut previous_result.nodes);
|
nodes.append(&mut previous_result.nodes);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for config in config_iter {
|
|
||||||
let result = self.process_configs(config, collect_nodes);
|
|
||||||
densely_chained = densely_chained && result.densely_chained;
|
|
||||||
if collect_nodes {
|
|
||||||
nodes_in_scope.extend(result.nodes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// an "unchained" SystemConfig is only densely chained if it has exactly one densely chained entry
|
|
||||||
if more_than_one_entry {
|
|
||||||
densely_chained = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessConfigsResult {
|
ProcessConfigsResult {
|
||||||
nodes: nodes_in_scope,
|
nodes,
|
||||||
densely_chained,
|
densely_chained,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user