Skip to content

Commit

Permalink
Split ScheduleGraph::process_configs function
Browse files Browse the repository at this point in the history
Just split it into several functions, because it is too large and
hard to read. No functional changes.
  • Loading branch information
stepancheg committed Nov 17, 2023
1 parent 0c9f265 commit ff26f45
Showing 1 changed file with 166 additions and 133 deletions.
299 changes: 166 additions & 133 deletions crates/bevy_ecs/src/schedule/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,163 @@ impl ScheduleGraph {
&self.conflicting_systems
}

fn process_config<T: ProcessNodeConfig>(
&mut self,
config: NodeConfig<T>,
collect_nodes: bool,
) -> ProcessConfigsResult {
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(),
}
}
}

fn apply_collective_conditions<T: ProcessNodeConfig>(
&mut self,
configs: &mut [NodeConfigs<T>],
collective_conditions: Vec<BoxedCondition>,
) {
let more_than_one_entry = configs.len() > 1;
if !collective_conditions.is_empty() {
if more_than_one_entry {
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();
} else {
for condition in collective_conditions {
configs[0].run_if_dyn(condition);
}
}
}
}

fn process_chained_configs<T: ProcessNodeConfig>(
&mut self,
mut configs: Vec<NodeConfigs<T>>,
collective_conditions: Vec<BoxedCondition>,
collect_nodes: bool,
) -> ProcessConfigsResult {
self.apply_collective_conditions(&mut configs, collective_conditions);

let mut config_iter = configs.into_iter();
let mut nodes_in_scope = Vec::new();
let Some(prev) = config_iter.next() else {
return ProcessConfigsResult {
nodes: Vec::new(),
densely_chained: true,
};
};
let mut previous_result = self.process_configs(prev, true);
let mut 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, ());
}
// 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 &current_result.nodes {
self.dependency
.graph
.add_edge(*last_in_prev, *current_node, ());
}
}
// The current list is currently "densely" chained, so we can simplify the graph by
// only chaining every item in the previous list to the first item in the current list
(false, true) => {
let first_in_current = current_result.nodes.first().unwrap();
for previous_node in &previous_result.nodes {
self.dependency
.graph
.add_edge(*previous_node, *first_in_current, ());
}
}
// 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 &current_result.nodes {
self.dependency
.graph
.add_edge(*previous_node, *current_node, ());
}
}
}
}

if collect_nodes {
nodes_in_scope.append(&mut previous_result.nodes);
}

previous_result = current_result;
}

// ensure the last config's nodes are added
if collect_nodes {
nodes_in_scope.append(&mut previous_result.nodes);
};

ProcessConfigsResult {
nodes: nodes_in_scope,
densely_chained,
}
}

fn process_unchained_configs<T: ProcessNodeConfig>(
&mut self,
mut configs: Vec<NodeConfigs<T>>,
collective_conditions: Vec<BoxedCondition>,
collect_nodes: bool,
) -> ProcessConfigsResult {
self.apply_collective_conditions(&mut configs, collective_conditions);

let more_than_one_entry = configs.len() > 1;
let mut nodes_in_scope = Vec::new();
let mut densely_chained = true;
for config in configs.into_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 {
nodes: nodes_in_scope,
densely_chained,
}
}

/// 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`].
Expand All @@ -583,141 +740,17 @@ impl ScheduleGraph {
collect_nodes: bool,
) -> ProcessConfigsResult {
match configs {
NodeConfigs::NodeConfig(config) => {
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::NodeConfig(config) => self.process_config(config, collect_nodes),
NodeConfigs::Configs {
mut configs,
configs,
collective_conditions,
chained,
} => {
let more_than_one_entry = configs.len() > 1;
if !collective_conditions.is_empty() {
if more_than_one_entry {
let set = self.create_anonymous_set();
for config in &mut configs {
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();
} else {
for condition in collective_conditions {
configs[0].run_if_dyn(condition);
}
}
}
let mut config_iter = configs.into_iter();
let mut nodes_in_scope = Vec::new();
let mut densely_chained = true;
if chained {
let Some(prev) = config_iter.next() else {
return ProcessConfigsResult {
nodes: Vec::new(),
densely_chained: true,
};
};
let mut previous_result = self.process_configs(prev, true);
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,
(),
);
}
// 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 &current_result.nodes {
self.dependency.graph.add_edge(
*last_in_prev,
*current_node,
(),
);
}
}
// The current list is currently "densely" chained, so we can simplify the graph by
// only chaining every item in the previous list to the first item in the current list
(false, true) => {
let first_in_current = current_result.nodes.first().unwrap();
for previous_node in &previous_result.nodes {
self.dependency.graph.add_edge(
*previous_node,
*first_in_current,
(),
);
}
}
// 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 &current_result.nodes {
self.dependency.graph.add_edge(
*previous_node,
*current_node,
(),
);
}
}
}
}

if collect_nodes {
nodes_in_scope.append(&mut previous_result.nodes);
}

previous_result = current_result;
}

// ensure the last config's nodes are added
if collect_nodes {
nodes_in_scope.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 {
nodes: nodes_in_scope,
densely_chained,
}
}
chained: true,
} => self.process_chained_configs(configs, collective_conditions, collect_nodes),
NodeConfigs::Configs {
configs,
collective_conditions,
chained: false,
} => self.process_unchained_configs(configs, collective_conditions, collect_nodes),
}
}

Expand Down

0 comments on commit ff26f45

Please sign in to comment.