diff --git a/benches/benches/bevy_ecs/scheduling/schedule.rs b/benches/benches/bevy_ecs/scheduling/schedule.rs index 40f39fd8b67101..49de37079b73ba 100644 --- a/benches/benches/bevy_ecs/scheduling/schedule.rs +++ b/benches/benches/bevy_ecs/scheduling/schedule.rs @@ -63,11 +63,18 @@ pub fn build_schedule(criterion: &mut Criterion) { // Use multiple different kinds of label to ensure that dynamic dispatch // doesn't somehow get optimized away. - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, SystemLabel)] + #[derive(Debug, Clone, Copy)] struct NumLabel(usize); - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, SystemLabel)] + #[derive(Debug, Clone, Copy, SystemLabel)] struct DummyLabel; + impl SystemLabel for NumLabel { + fn as_str(&self) -> &'static str { + let s = self.0.to_string(); + Box::leak(s.into_boxed_str()) + } + } + let mut group = criterion.benchmark_group("build_schedule"); group.warm_up_time(std::time::Duration::from_millis(500)); group.measurement_time(std::time::Duration::from_secs(15)); @@ -75,7 +82,10 @@ pub fn build_schedule(criterion: &mut Criterion) { // Method: generate a set of `graph_size` systems which have a One True Ordering. // Add system to the stage with full constraints. Hopefully this should be maximimally // difficult for bevy to figure out. - let labels: Vec<_> = (0..1000).map(NumLabel).collect(); + // Also, we are performing the `as_label` operation outside of the loop since that + // requires an allocation and a leak. This is not something that would be necessary in a + // real scenario, just a contrivance for the benchmark. + let labels: Vec<_> = (0..1000).map(|i| NumLabel(i).as_label()).collect(); // Benchmark graphs of different sizes. for graph_size in [100, 500, 1000] { diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 4d72c15e7d4ed0..0e717ca632e269 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -56,7 +56,7 @@ pub struct App { pub runner: Box, /// A container of [`Stage`]s set to be run in a linear order. pub schedule: Schedule, - sub_apps: HashMap, SubApp>, + sub_apps: HashMap, } /// Each `SubApp` has its own [`Schedule`] and [`World`], enabling a separation of concerns. @@ -879,7 +879,7 @@ impl App { sub_app_runner: impl Fn(&mut World, &mut App) + 'static, ) -> &mut Self { self.sub_apps.insert( - Box::new(label), + label.as_label(), SubApp { app, runner: Box::new(sub_app_runner), @@ -896,15 +896,16 @@ impl App { pub fn sub_app_mut(&mut self, label: impl AppLabel) -> &mut App { match self.get_sub_app_mut(label) { Ok(app) => app, - Err(label) => panic!("Sub-App with label '{:?}' does not exist", label), + Err(label) => panic!("Sub-App with label '{:?}' does not exist", label.as_str()), } } /// Retrieves a `SubApp` inside this [`App`] with the given label, if it exists. Otherwise returns /// an [`Err`] containing the given label. - pub fn get_sub_app_mut(&mut self, label: impl AppLabel) -> Result<&mut App, impl AppLabel> { + pub fn get_sub_app_mut(&mut self, label: impl AppLabel) -> Result<&mut App, AppLabelId> { + let label = label.as_label(); self.sub_apps - .get_mut((&label) as &dyn AppLabel) + .get_mut(&label) .map(|sub_app| &mut sub_app.app) .ok_or(label) } @@ -917,7 +918,7 @@ impl App { pub fn sub_app(&self, label: impl AppLabel) -> &App { match self.get_sub_app(label) { Ok(app) => app, - Err(label) => panic!("Sub-App with label '{:?}' does not exist", label), + Err(label) => panic!("Sub-App with label '{:?}' does not exist", label.as_str()), } } @@ -925,7 +926,7 @@ impl App { /// an [`Err`] containing the given label. pub fn get_sub_app(&self, label: impl AppLabel) -> Result<&App, impl AppLabel> { self.sub_apps - .get((&label) as &dyn AppLabel) + .get(&label.as_label()) .map(|sub_app| &sub_app.app) .ok_or(label) } diff --git a/crates/bevy_ecs/src/schedule/label.rs b/crates/bevy_ecs/src/schedule/label.rs index 5235dc5837692c..28d6c10b3b2809 100644 --- a/crates/bevy_ecs/src/schedule/label.rs +++ b/crates/bevy_ecs/src/schedule/label.rs @@ -5,8 +5,3 @@ define_label!(StageLabel); define_label!(SystemLabel); define_label!(AmbiguitySetLabel); define_label!(RunCriteriaLabel); - -pub(crate) type BoxedStageLabel = Box; -pub(crate) type BoxedSystemLabel = Box; -pub(crate) type BoxedAmbiguitySetLabel = Box; -pub(crate) type BoxedRunCriteriaLabel = Box; diff --git a/crates/bevy_ecs/src/schedule/mod.rs b/crates/bevy_ecs/src/schedule/mod.rs index 1aab0f0f4414dc..2e1bd167caedf2 100644 --- a/crates/bevy_ecs/src/schedule/mod.rs +++ b/crates/bevy_ecs/src/schedule/mod.rs @@ -38,8 +38,8 @@ use bevy_utils::HashMap; /// runs indefinitely. #[derive(Default)] pub struct Schedule { - stages: HashMap>, - stage_order: Vec, + stages: HashMap>, + stage_order: Vec, run_criteria: BoxedRunCriteria, } @@ -109,9 +109,9 @@ impl Schedule { /// schedule.add_stage("my_stage", SystemStage::parallel()); /// ``` pub fn add_stage(&mut self, label: impl StageLabel, stage: S) -> &mut Self { - let label: Box = Box::new(label); - self.stage_order.push(label.clone()); - let prev = self.stages.insert(label.clone(), Box::new(stage)); + let label = label.as_label(); + self.stage_order.push(label); + let prev = self.stages.insert(label, Box::new(stage)); assert!(prev.is_none(), "Stage already exists: {:?}.", label); self } @@ -133,18 +133,18 @@ impl Schedule { label: impl StageLabel, stage: S, ) -> &mut Self { - let label: Box = Box::new(label); - let target = &target as &dyn StageLabel; + let label = label.as_label(); + let target = target.as_label(); let target_index = self .stage_order .iter() .enumerate() - .find(|(_i, stage_label)| &***stage_label == target) + .find(|(_i, stage_label)| **stage_label == target) .map(|(i, _)| i) .unwrap_or_else(|| panic!("Target stage does not exist: {:?}.", target)); - self.stage_order.insert(target_index + 1, label.clone()); - let prev = self.stages.insert(label.clone(), Box::new(stage)); + self.stage_order.insert(target_index + 1, label); + let prev = self.stages.insert(label, Box::new(stage)); assert!(prev.is_none(), "Stage already exists: {:?}.", label); self } @@ -167,18 +167,18 @@ impl Schedule { label: impl StageLabel, stage: S, ) -> &mut Self { - let label: Box = Box::new(label); - let target = &target as &dyn StageLabel; + let label = label.as_label(); + let target = target.as_label(); let target_index = self .stage_order .iter() .enumerate() - .find(|(_i, stage_label)| &***stage_label == target) + .find(|(_i, stage_label)| **stage_label == target) .map(|(i, _)| i) .unwrap_or_else(|| panic!("Target stage does not exist: {:?}.", target)); - self.stage_order.insert(target_index, label.clone()); - let prev = self.stages.insert(label.clone(), Box::new(stage)); + self.stage_order.insert(target_index, label); + let prev = self.stages.insert(label, Box::new(stage)); assert!(prev.is_none(), "Stage already exists: {:?}.", label); self } @@ -213,7 +213,7 @@ impl Schedule { let stage = self .get_stage_mut::(&stage_label) - .unwrap_or_else(move || stage_not_found(&stage_label)); + .unwrap_or_else(move || stage_not_found(&stage_label.as_label())); stage.add_system(system); self } @@ -282,7 +282,10 @@ impl Schedule { func: F, ) -> &mut Self { let stage = self.get_stage_mut::(&label).unwrap_or_else(move || { - panic!("stage '{:?}' does not exist or is the wrong type", label) + panic!( + "stage '{:?}' does not exist or is the wrong type", + label.as_label() + ) }); func(stage); self @@ -305,7 +308,7 @@ impl Schedule { /// ``` pub fn get_stage(&self, label: &dyn StageLabel) -> Option<&T> { self.stages - .get(label) + .get(&label.as_label()) .and_then(|stage| stage.downcast_ref::()) } @@ -326,7 +329,7 @@ impl Schedule { /// ``` pub fn get_stage_mut(&mut self, label: &dyn StageLabel) -> Option<&mut T> { self.stages - .get_mut(label) + .get_mut(&label.as_label()) .and_then(|stage| stage.downcast_mut::()) } @@ -341,10 +344,10 @@ impl Schedule { } /// Iterates over all of schedule's stages and their labels, in execution order. - pub fn iter_stages(&self) -> impl Iterator { + pub fn iter_stages(&self) -> impl Iterator { self.stage_order .iter() - .map(move |label| (&**label, &*self.stages[label])) + .map(move |&label| (label, &*self.stages[&label])) } } diff --git a/crates/bevy_ecs/src/schedule/run_criteria.rs b/crates/bevy_ecs/src/schedule/run_criteria.rs index fb58136508b777..575a63080d3fc5 100644 --- a/crates/bevy_ecs/src/schedule/run_criteria.rs +++ b/crates/bevy_ecs/src/schedule/run_criteria.rs @@ -1,5 +1,5 @@ use crate::{ - schedule::{BoxedRunCriteriaLabel, GraphNode, RunCriteriaLabel}, + schedule::{GraphNode, RunCriteriaLabel, RunCriteriaLabelId}, system::{BoxedSystem, IntoSystem, Local}, world::World, }; @@ -104,9 +104,9 @@ pub(crate) enum RunCriteriaInner { pub(crate) struct RunCriteriaContainer { pub(crate) should_run: ShouldRun, pub(crate) inner: RunCriteriaInner, - pub(crate) label: Option, - pub(crate) before: Vec, - pub(crate) after: Vec, + pub(crate) label: Option, + pub(crate) before: Vec, + pub(crate) after: Vec, } impl RunCriteriaContainer { @@ -139,7 +139,7 @@ impl RunCriteriaContainer { } impl GraphNode for RunCriteriaContainer { - type Label = BoxedRunCriteriaLabel; + type Label = RunCriteriaLabelId; fn name(&self) -> Cow<'static, str> { match &self.inner { @@ -148,7 +148,7 @@ impl GraphNode for RunCriteriaContainer { } } - fn labels(&self) -> &[BoxedRunCriteriaLabel] { + fn labels(&self) -> &[RunCriteriaLabelId] { if let Some(ref label) = self.label { std::slice::from_ref(label) } else { @@ -156,18 +156,18 @@ impl GraphNode for RunCriteriaContainer { } } - fn before(&self) -> &[BoxedRunCriteriaLabel] { + fn before(&self) -> &[RunCriteriaLabelId] { &self.before } - fn after(&self) -> &[BoxedRunCriteriaLabel] { + fn after(&self) -> &[RunCriteriaLabelId] { &self.after } } pub enum RunCriteriaDescriptorOrLabel { Descriptor(RunCriteriaDescriptor), - Label(BoxedRunCriteriaLabel), + Label(RunCriteriaLabelId), } #[derive(Clone, Copy)] @@ -178,10 +178,10 @@ pub(crate) enum DuplicateLabelStrategy { pub struct RunCriteriaDescriptor { pub(crate) system: RunCriteriaSystem, - pub(crate) label: Option, + pub(crate) label: Option, pub(crate) duplicate_label_strategy: DuplicateLabelStrategy, - pub(crate) before: Vec, - pub(crate) after: Vec, + pub(crate) before: Vec, + pub(crate) after: Vec, } pub(crate) enum RunCriteriaSystem { @@ -222,12 +222,12 @@ where } } -impl IntoRunCriteria for L +impl IntoRunCriteria for L where L: RunCriteriaLabel, { fn into(self) -> RunCriteriaDescriptorOrLabel { - RunCriteriaDescriptorOrLabel::Label(Box::new(self)) + RunCriteriaDescriptorOrLabel::Label(self.as_label()) } } @@ -254,24 +254,24 @@ pub trait RunCriteriaDescriptorCoercion { impl RunCriteriaDescriptorCoercion<()> for RunCriteriaDescriptor { fn label(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { - self.label = Some(Box::new(label)); + self.label = Some(label.as_label()); self.duplicate_label_strategy = DuplicateLabelStrategy::Panic; self } fn label_discard_if_duplicate(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { - self.label = Some(Box::new(label)); + self.label = Some(label.as_label()); self.duplicate_label_strategy = DuplicateLabelStrategy::Discard; self } fn before(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { - self.before.push(Box::new(label)); + self.before.push(label.as_label()); self } fn after(mut self, label: impl RunCriteriaLabel) -> RunCriteriaDescriptor { - self.after.push(Box::new(label)); + self.after.push(label.as_label()); self } } @@ -327,7 +327,7 @@ where } pub struct RunCriteria { - label: BoxedRunCriteriaLabel, + label: RunCriteriaLabelId, } impl RunCriteria { @@ -342,7 +342,7 @@ impl RunCriteria { label: None, duplicate_label_strategy: DuplicateLabelStrategy::Panic, before: vec![], - after: vec![Box::new(label)], + after: vec![label.as_label()], } } } diff --git a/crates/bevy_ecs/src/schedule/stage.rs b/crates/bevy_ecs/src/schedule/stage.rs index 014423e2c4f135..a14a5db7be32a7 100644 --- a/crates/bevy_ecs/src/schedule/stage.rs +++ b/crates/bevy_ecs/src/schedule/stage.rs @@ -4,11 +4,11 @@ use crate::{ prelude::IntoSystem, schedule::{ graph_utils::{self, DependencyGraphError}, - BoxedRunCriteria, BoxedRunCriteriaLabel, BoxedSystemLabel, DuplicateLabelStrategy, - ExclusiveSystemContainer, GraphNode, InsertionPoint, ParallelExecutor, - ParallelSystemContainer, ParallelSystemExecutor, RunCriteriaContainer, - RunCriteriaDescriptor, RunCriteriaDescriptorOrLabel, RunCriteriaInner, ShouldRun, - SingleThreadedExecutor, SystemContainer, SystemDescriptor, SystemSet, + BoxedRunCriteria, DuplicateLabelStrategy, ExclusiveSystemContainer, GraphNode, + InsertionPoint, ParallelExecutor, ParallelSystemContainer, ParallelSystemExecutor, + RunCriteriaContainer, RunCriteriaDescriptor, RunCriteriaDescriptorOrLabel, + RunCriteriaInner, RunCriteriaLabelId, ShouldRun, SingleThreadedExecutor, SystemContainer, + SystemDescriptor, SystemLabelId, SystemSet, }, world::{World, WorldId}, }; @@ -171,7 +171,7 @@ impl SystemStage { container.run_criteria_label = Some(label); } Some(RunCriteriaDescriptorOrLabel::Descriptor(criteria_descriptor)) => { - container.run_criteria_label = criteria_descriptor.label.clone(); + container.run_criteria_label = criteria_descriptor.label; container.run_criteria_index = Some(self.add_run_criteria_internal(criteria_descriptor)); } @@ -205,7 +205,7 @@ impl SystemStage { container.run_criteria_label = Some(label); } Some(RunCriteriaDescriptorOrLabel::Descriptor(criteria_descriptor)) => { - container.run_criteria_label = criteria_descriptor.label.clone(); + container.run_criteria_label = criteria_descriptor.label; container.run_criteria_index = Some(self.add_run_criteria_internal(criteria_descriptor)); } @@ -301,11 +301,11 @@ impl SystemStage { match system { SystemDescriptor::Exclusive(descriptor) => { descriptor.run_criteria = - Some(RunCriteriaDescriptorOrLabel::Label(label.clone())); + Some(RunCriteriaDescriptorOrLabel::Label(label)); } SystemDescriptor::Parallel(descriptor) => { descriptor.run_criteria = - Some(RunCriteriaDescriptorOrLabel::Label(label.clone())); + Some(RunCriteriaDescriptorOrLabel::Label(label)); } } } @@ -372,7 +372,7 @@ impl SystemStage { .enumerate() .filter_map(|(index, mut container)| { let new_index = index - filtered_criteria; - let label = container.label.clone(); + let label = container.label; if let Some(strategy) = uninitialized_criteria.get(&index) { if let Some(ref label) = label { if let Some(duplicate_index) = criteria_labels.get(label) { @@ -621,10 +621,8 @@ impl SystemStage { /// Returns a map of run criteria labels to their indices. fn process_run_criteria( &mut self, - ) -> Result< - HashMap, - DependencyGraphError>, - > { + ) -> Result, DependencyGraphError>> + { let graph = graph_utils::build_dependency_graph(&self.run_criteria); let order = graph_utils::topological_order(&graph)?; let mut order_inverted = order.iter().enumerate().collect::>(); @@ -637,7 +635,7 @@ impl SystemStage { criteria .label .as_ref() - .map(|label| (label.clone(), order_inverted[index].0)) + .map(|&label| (label, order_inverted[index].0)) }) .collect(); for criteria in &mut self.run_criteria { @@ -680,8 +678,8 @@ impl SystemStage { /// and run criteria. fn process_systems( systems: &mut Vec, - run_criteria_labels: &HashMap, -) -> Result<(), DependencyGraphError>> { + run_criteria_labels: &HashMap, +) -> Result<(), DependencyGraphError>> { let mut graph = graph_utils::build_dependency_graph(systems); let order = graph_utils::topological_order(&graph)?; let mut order_inverted = order.iter().enumerate().collect::>(); @@ -974,9 +972,9 @@ impl Stage for SystemStage { mod tests { use crate::{ schedule::{ - BoxedSystemLabel, ExclusiveSystemDescriptorCoercion, ParallelSystemDescriptorCoercion, - RunCriteria, RunCriteriaDescriptorCoercion, ShouldRun, SingleThreadedExecutor, Stage, - SystemSet, SystemStage, + ExclusiveSystemDescriptorCoercion, ParallelSystemDescriptorCoercion, RunCriteria, + RunCriteriaDescriptorCoercion, ShouldRun, SingleThreadedExecutor, Stage, SystemLabel, + SystemLabelId, SystemSet, SystemStage, }, system::{In, IntoExclusiveSystem, Local, Query, ResMut}, world::World, @@ -1609,23 +1607,21 @@ mod tests { fn find_ambiguities_first_str_labels( systems: &[impl SystemContainer], - ) -> Vec<(BoxedSystemLabel, BoxedSystemLabel)> { + ) -> Vec<(SystemLabelId, SystemLabelId)> { find_ambiguities(systems) .drain(..) .map(|(index_a, index_b, _conflicts)| { ( - systems[index_a] + *systems[index_a] .labels() .iter() - .find(|a| (&***a).type_id() == std::any::TypeId::of::<&str>()) - .unwrap() - .clone(), - systems[index_b] + .find(|a| a.type_id() == std::any::TypeId::of::<&str>()) + .unwrap(), + *systems[index_b] .labels() .iter() - .find(|a| (&***a).type_id() == std::any::TypeId::of::<&str>()) - .unwrap() - .clone(), + .find(|a| a.type_id() == std::any::TypeId::of::<&str>()) + .unwrap(), ) }) .collect() @@ -1657,8 +1653,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "1".as_label())) ); assert_eq!(ambiguities.len(), 1); @@ -1672,8 +1668,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "1".as_label())) ); assert_eq!(ambiguities.len(), 1); @@ -1697,12 +1693,12 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("0"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("0"))) + ambiguities.contains(&("0".as_label(), "3".as_label())) + || ambiguities.contains(&("3".as_label(), "0".as_label())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "1".as_label())) ); assert_eq!(ambiguities.len(), 2); @@ -1716,8 +1712,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("0"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("0"))) + ambiguities.contains(&("0".as_label(), "3".as_label())) + || ambiguities.contains(&("3".as_label(), "0".as_label())) ); assert_eq!(ambiguities.len(), 1); @@ -1729,8 +1725,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("0"), Box::new("1"))) - || ambiguities.contains(&(Box::new("1"), Box::new("0"))) + ambiguities.contains(&("0".as_label(), "1".as_label())) + || ambiguities.contains(&("1".as_label(), "0".as_label())) ); assert_eq!(ambiguities.len(), 1); @@ -1742,8 +1738,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("2"))) - || ambiguities.contains(&(Box::new("2"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "2".as_label())) + || ambiguities.contains(&("2".as_label(), "1".as_label())) ); assert_eq!(ambiguities.len(), 1); @@ -1756,8 +1752,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("2"))) - || ambiguities.contains(&(Box::new("2"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "2".as_label())) + || ambiguities.contains(&("2".as_label(), "1".as_label())) ); assert_eq!(ambiguities.len(), 1); @@ -1780,8 +1776,8 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("2"))) - || ambiguities.contains(&(Box::new("2"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "2".as_label())) + || ambiguities.contains(&("2".as_label(), "1".as_label())) ); assert_eq!(ambiguities.len(), 1); @@ -1810,28 +1806,28 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("2"))) - || ambiguities.contains(&(Box::new("2"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "2".as_label())) + || ambiguities.contains(&("2".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "3".as_label())) + || ambiguities.contains(&("3".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "3".as_label())) + || ambiguities.contains(&("3".as_label(), "2".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "2".as_label())) ); assert!( - ambiguities.contains(&(Box::new("3"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("3"))) + ambiguities.contains(&("3".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "3".as_label())) ); assert_eq!(ambiguities.len(), 6); @@ -1891,12 +1887,12 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.parallel); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "2".as_label())) ); assert_eq!(ambiguities.len(), 2); @@ -1925,28 +1921,28 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.exclusive_at_start); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "3".as_label())) + || ambiguities.contains(&("3".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "3".as_label())) + || ambiguities.contains(&("3".as_label(), "2".as_label())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "2".as_label())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("5"))) - || ambiguities.contains(&(Box::new("5"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "5".as_label())) + || ambiguities.contains(&("5".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("5"))) - || ambiguities.contains(&(Box::new("5"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "5".as_label())) + || ambiguities.contains(&("5".as_label(), "2".as_label())) ); assert_eq!(ambiguities.len(), 6); @@ -1962,20 +1958,20 @@ mod tests { stage.rebuild_orders_and_dependencies(); let ambiguities = find_ambiguities_first_str_labels(&stage.exclusive_at_start); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("3"))) - || ambiguities.contains(&(Box::new("3"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "3".as_label())) + || ambiguities.contains(&("3".as_label(), "2".as_label())) ); assert!( - ambiguities.contains(&(Box::new("1"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("1"))) + ambiguities.contains(&("1".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "1".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("4"))) - || ambiguities.contains(&(Box::new("4"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "4".as_label())) + || ambiguities.contains(&("4".as_label(), "2".as_label())) ); assert!( - ambiguities.contains(&(Box::new("2"), Box::new("5"))) - || ambiguities.contains(&(Box::new("5"), Box::new("2"))) + ambiguities.contains(&("2".as_label(), "5".as_label())) + || ambiguities.contains(&("5".as_label(), "2".as_label())) ); assert_eq!(ambiguities.len(), 4); diff --git a/crates/bevy_ecs/src/schedule/state.rs b/crates/bevy_ecs/src/schedule/state.rs index 1693f0adce7e36..96e4409da98984 100644 --- a/crates/bevy_ecs/src/schedule/state.rs +++ b/crates/bevy_ecs/src/schedule/state.rs @@ -53,47 +53,19 @@ enum ScheduledOperation { } #[derive(Debug, PartialEq, Eq, Clone, Hash)] -enum StateCallback { - Update, - InactiveUpdate, - InStackUpdate, - Enter, - Exit, - Pause, - Resume, -} - -impl StateCallback { - fn into_label(self, state: T) -> StateRunCriteriaLabel - where - T: StateData, - { - StateRunCriteriaLabel(state, self) - } -} - -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -struct StateRunCriteriaLabel(T, StateCallback); -impl RunCriteriaLabel for StateRunCriteriaLabel -where - T: StateData, -{ - fn dyn_clone(&self) -> Box { - Box::new(self.clone()) - } -} - -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -struct DriverLabel(TypeId); +struct DriverLabel(TypeId, &'static str); impl RunCriteriaLabel for DriverLabel { - fn dyn_clone(&self) -> Box { - Box::new(self.clone()) + fn type_id(&self) -> core::any::TypeId { + self.0 + } + fn as_str(&self) -> &'static str { + self.1 } } impl DriverLabel { fn of() -> Self { - Self(TypeId::of::()) + Self(TypeId::of::(), std::any::type_name::()) } } @@ -102,17 +74,14 @@ where T: StateData, { pub fn on_update(pred: T) -> RunCriteriaDescriptor { - let pred_clone = pred.clone(); (move |state: Res>| { state.stack.last().unwrap() == &pred && state.transition.is_none() }) .chain(should_run_adapter::) .after(DriverLabel::of::()) - .label_discard_if_duplicate(StateCallback::Update.into_label(pred_clone)) } pub fn on_inactive_update(pred: T) -> RunCriteriaDescriptor { - let pred_clone = pred.clone(); (move |state: Res>, mut is_inactive: Local| match &state.transition { Some(StateTransition::Pausing(ref relevant, _)) | Some(StateTransition::Resuming(_, ref relevant)) => { @@ -126,11 +95,9 @@ where }) .chain(should_run_adapter::) .after(DriverLabel::of::()) - .label_discard_if_duplicate(StateCallback::InactiveUpdate.into_label(pred_clone)) } pub fn on_in_stack_update(pred: T) -> RunCriteriaDescriptor { - let pred_clone = pred.clone(); (move |state: Res>, mut is_in_stack: Local| match &state.transition { Some(StateTransition::Entering(ref relevant, _)) | Some(StateTransition::ExitingToResume(_, ref relevant)) @@ -151,11 +118,9 @@ where }) .chain(should_run_adapter::) .after(DriverLabel::of::()) - .label_discard_if_duplicate(StateCallback::InStackUpdate.into_label(pred_clone)) } pub fn on_enter(pred: T) -> RunCriteriaDescriptor { - let pred_clone = pred.clone(); (move |state: Res>| { state .transition @@ -168,11 +133,9 @@ where }) .chain(should_run_adapter::) .after(DriverLabel::of::()) - .label_discard_if_duplicate(StateCallback::Enter.into_label(pred_clone)) } pub fn on_exit(pred: T) -> RunCriteriaDescriptor { - let pred_clone = pred.clone(); (move |state: Res>| { state .transition @@ -185,11 +148,9 @@ where }) .chain(should_run_adapter::) .after(DriverLabel::of::()) - .label_discard_if_duplicate(StateCallback::Exit.into_label(pred_clone)) } pub fn on_pause(pred: T) -> RunCriteriaDescriptor { - let pred_clone = pred.clone(); (move |state: Res>| { state .transition @@ -201,11 +162,9 @@ where }) .chain(should_run_adapter::) .after(DriverLabel::of::()) - .label_discard_if_duplicate(StateCallback::Pause.into_label(pred_clone)) } pub fn on_resume(pred: T) -> RunCriteriaDescriptor { - let pred_clone = pred.clone(); (move |state: Res>| { state .transition @@ -217,7 +176,6 @@ where }) .chain(should_run_adapter::) .after(DriverLabel::of::()) - .label_discard_if_duplicate(StateCallback::Resume.into_label(pred_clone)) } pub fn on_update_set(s: T) -> SystemSet { diff --git a/crates/bevy_ecs/src/schedule/system_container.rs b/crates/bevy_ecs/src/schedule/system_container.rs index a82969a5d4c322..51d0962489143c 100644 --- a/crates/bevy_ecs/src/schedule/system_container.rs +++ b/crates/bevy_ecs/src/schedule/system_container.rs @@ -2,15 +2,15 @@ use crate::{ component::ComponentId, query::Access, schedule::{ - BoxedAmbiguitySetLabel, BoxedRunCriteriaLabel, BoxedSystemLabel, ExclusiveSystemDescriptor, - GraphNode, ParallelSystemDescriptor, + AmbiguitySetLabelId, ExclusiveSystemDescriptor, GraphNode, ParallelSystemDescriptor, + RunCriteriaLabelId, SystemLabelId, }, system::{ExclusiveSystem, System}, }; use std::borrow::Cow; /// System metadata like its name, labels, order requirements and component access. -pub trait SystemContainer: GraphNode