Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fast and correct one-shot systems with a system registry resource #4090

Closed
wants to merge 61 commits into from
Closed
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
3e6a8c5
Basic functionality
alice-i-cecile Mar 3, 2022
f9b16c2
commands.run_system
alice-i-cecile Mar 3, 2022
8e32c74
Add SystemRegistry resource as part of CorePlugin
alice-i-cecile Mar 3, 2022
961af58
Run system by TypeId
alice-i-cecile Mar 3, 2022
d7ece72
Fix doc links
alice-i-cecile Mar 3, 2022
f54db1f
run_system_by_type_id for World and Commands
alice-i-cecile Mar 3, 2022
4fc35e5
Always flush commands from systems
alice-i-cecile Mar 3, 2022
a9be933
Always initialize SystemRegistry on the `World`
alice-i-cecile Mar 3, 2022
fed175c
Add test suite
alice-i-cecile Mar 3, 2022
b883bca
Doc improvements
alice-i-cecile Mar 7, 2022
ee33630
Store registered systems by their system labels
alice-i-cecile Mar 26, 2022
b520291
Ensure that run_system always runs the system exactly once
alice-i-cecile Mar 26, 2022
7041713
Advertise SystemRegistry in SystemState docs
alice-i-cecile Mar 26, 2022
1a5e308
Doc tests for SystemRegistry
alice-i-cecile Mar 26, 2022
6f3a676
Improve ergonomics of the register_system API
alice-i-cecile Mar 26, 2022
ebe2f29
Improve run_by_label API ergonomics
alice-i-cecile Mar 26, 2022
3e41300
Improve ergonomics of registering systems
alice-i-cecile Mar 26, 2022
0f0a6dd
Note limitations
alice-i-cecile Mar 27, 2022
870b12d
Remove the need to manually update archetypes
alice-i-cecile Apr 18, 2022
ba66966
Move SystemRegistry to a field on `World`
alice-i-cecile Apr 18, 2022
5baac51
Revert "Move SystemRegistry to a field on `World`"
alice-i-cecile Apr 18, 2022
3be2a2e
Clippy fixes
alice-i-cecile Jun 29, 2022
4feb974
Merge remote-tracking branch 'origin/main' into system_registry
alice-i-cecile Jun 29, 2022
4fe2937
Clippy fix
alice-i-cecile Jun 29, 2022
38fd422
System recursion should fail
alice-i-cecile Jun 29, 2022
641f5df
Documentation improvements
alice-i-cecile Jun 29, 2022
854a805
Nicer error handling
alice-i-cecile Jun 30, 2022
7f41af9
Return index from register system methods
alice-i-cecile Jun 30, 2022
5c35c51
Fix off by one error
alice-i-cecile Jun 30, 2022
681a6fc
Reduce noisy returns
alice-i-cecile Jun 30, 2022
091e50f
Fix broken tests
alice-i-cecile Jun 30, 2022
5f3925e
Add example
alice-i-cecile Jun 30, 2022
e812bed
Improve ergonomics of register_system method
alice-i-cecile Jun 30, 2022
79aba5c
Formatting
alice-i-cecile Jun 30, 2022
7c02da4
Expose run_systems_by_boxed_label method
alice-i-cecile Jun 30, 2022
cdd8cfc
Create matching methods on App
alice-i-cecile Jun 30, 2022
e6094c6
Polish example
alice-i-cecile Jun 30, 2022
61db824
Update examples README per CI
alice-i-cecile Jun 30, 2022
afec804
Simplify system_registry doc tests
alice-i-cecile Jun 30, 2022
9423b49
Fix broken link
alice-i-cecile Jun 30, 2022
ebfca10
Add Callback type to bevy_ecs itself
alice-i-cecile Jun 30, 2022
1088dc6
Implement PartialEq and Eq for Callback
alice-i-cecile Jun 30, 2022
31b2277
Implement Hash for Callback
alice-i-cecile Jun 30, 2022
f505e2d
Change run_system_by_boxed_label to run_callback
alice-i-cecile Jun 30, 2022
d451282
Fix doc example
alice-i-cecile Jun 30, 2022
89fa516
Manually implement Hash
alice-i-cecile Jun 30, 2022
6cc0cb9
Fix doc example (for real?)
alice-i-cecile Jun 30, 2022
5f29c93
Avoid box allocation
alice-i-cecile Jun 30, 2022
707ec5d
Mostly fix doc example
alice-i-cecile Jul 1, 2022
e7b6190
Remove frustrating doc example
alice-i-cecile Jul 1, 2022
0b46807
Merge branch 'main' into system_registry
alice-i-cecile Jul 29, 2022
ddfd7dc
Typo fix
alice-i-cecile Jul 29, 2022
4d312e7
Clarify drawbacks of SystemState
alice-i-cecile Jul 29, 2022
8cf91a4
Punctuation
alice-i-cecile Jul 29, 2022
b2f5bf7
Typo
alice-i-cecile Jul 29, 2022
2254d4f
Fix mistake from merge conflict
alice-i-cecile Jul 29, 2022
25c66db
Remove vague warning about callbacks
alice-i-cecile Jul 29, 2022
3ad29fd
Add Send and Sync bounds to label traits
alice-i-cecile Jul 29, 2022
ac1c2aa
Clean up docs and naming around system registration
alice-i-cecile Jul 29, 2022
e730525
Make App and World APIs consistent
alice-i-cecile Jul 29, 2022
55e61e1
Make doc links on higher level methods more useful
alice-i-cecile Jul 29, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,16 @@ description = "Shows how to iterate over combinations of query results"
category = "ECS (Entity Component System)"
wasm = true

[[example]]
name = "one_shot_systems"
path = "examples/ecs/one_shot_systems.rs"

[package.metadata.example.one_shot_systems]
name = "One Shot Systems"
description = "Shows how to flexibly run systems without scheduling them"
category = "ECS (Entity Component System)"
wasm = false

[[example]]
name = "parallel_query"
path = "examples/ecs/parallel_query.rs"
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_app/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod app;
mod plugin;
mod plugin_group;
mod schedule_runner;
mod system_registry;

#[cfg(feature = "bevy_ci_testing")]
mod ci_testing;
Expand Down
67 changes: 67 additions & 0 deletions crates/bevy_app/src/system_registry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use crate::App;
use bevy_ecs::prelude::*;
use bevy_ecs::system::{Callback, SystemRegistryError};

impl App {
/// Registers the supplied system in the [`SystemRegistry`](bevy_ecs::system::SystemRegistry) resource.
///
/// Calls the method of the same name on [`SystemRegistry`](bevy_ecs::system::SystemRegistry).
#[inline]
pub fn register_system<Params, S: IntoSystem<(), (), Params> + 'static>(
&mut self,
system: S,
) -> &mut Self {
self.world.register_system(system);
self
}

/// Register system a system with any number of [`SystemLabel`]s.
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
///
/// Calls the method of the same name on [`SystemRegistry`].
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
///
/// [`SystemRegistry`]: bevy_ecs::system::SystemRegistry
pub fn register_system_with_labels<
Params,
S: IntoSystem<(), (), Params> + 'static,
LI: IntoIterator<Item = L>,
L: SystemLabel,
>(
&mut self,
system: S,
labels: LI,
) -> &mut Self {
self.world.register_system_with_labels(system, labels);
self
}

/// Runs the supplied system on the [`World`] a single time.
///
/// Calls the method of the same name on [`SystemRegistry`](bevy_ecs::system::SystemRegistry).
#[inline]
pub fn run_system<Params, S: IntoSystem<(), (), Params> + 'static>(
&mut self,
system: S,
) -> &mut Self {
self.world.run_system(system);
self
}

/// Runs the systems corresponding to the supplied [`SystemLabel`] on the [`World`] a single time.
///
/// Calls the method of the same name on [`SystemRegistry`](bevy_ecs::system::SystemRegistry).
#[inline]
pub fn run_systems_by_label<L: SystemLabel>(
&mut self,
label: L,
) -> Result<(), SystemRegistryError> {
self.world.run_systems_by_label(label)
}

/// Run the systems corresponding to the label stored in the provided [`Callback`]
///
/// Calls the method of the same name on [`SystemRegistry`](bevy_ecs::system::SystemRegistry).
#[inline]
pub fn run_callback(&mut self, callback: Callback) -> Result<(), SystemRegistryError> {
self.world.run_callback(callback)
}
}
33 changes: 33 additions & 0 deletions crates/bevy_ecs/src/system/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use crate::{
bundle::Bundle,
component::Component,
entity::{Entities, Entity},
schedule::SystemLabel,
system::{Callback, IntoSystem, RunSystemCommand, RunSystemsByLabelCommand},
world::{FromWorld, World},
};
use bevy_utils::tracing::{error, warn};
Expand Down Expand Up @@ -362,6 +364,37 @@ impl<'w, 's> Commands<'w, 's> {
});
}

/// Runs the supplied system on the [`World`] a single time.
///
/// Calls the method of the same name on [`SystemRegistry`](crate::system::SystemRegistry).
pub fn run_system<
Params: Send + Sync + 'static,
S: IntoSystem<(), (), Params> + Send + Sync + 'static,
>(
&mut self,
system: S,
) {
self.queue.push(RunSystemCommand::new(system));
}

/// Runs the systems corresponding to the supplied [`SystemLabel`] on the [`World`] a single time.
///
/// Calls the method of the same name on [`SystemRegistry`](crate::system::SystemRegistry).
pub fn run_systems_by_label(&mut self, label: impl SystemLabel) {
self.queue.push(RunSystemsByLabelCommand {
callback: Callback {
label: Box::new(label),
},
});
}

/// Run the systems corresponding to the label stored in the provided [`Callback`]
///
/// Calls the method of the same name on [`SystemRegistry`](crate::system::SystemRegistry).
pub fn run_callback(&mut self, callback: Callback) {
self.queue.push(RunSystemsByLabelCommand { callback });
}

/// Adds a command directly to the command list.
///
/// # Example
Expand Down
19 changes: 18 additions & 1 deletion crates/bevy_ecs/src/system/function_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ impl SystemMeta {
// (to avoid the need for unwrapping to retrieve SystemMeta)
/// Holds on to persistent state required to drive [`SystemParam`] for a [`System`].
///
/// This is a very powerful and convenient tool for working with exclusive world access,
/// This is a powerful and convenient tool for working with exclusive world access,
/// allowing you to fetch data from the [`World`] as if you were running a [`System`].
/// However, simply calling `world::run_system(my_system)` using a [`SystemRegistry`](crate::system::SystemRegistry)
/// can be significantly simpler and more reliable.
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
///
/// Borrow-checking is handled for you, allowing you to mutably access multiple compatible system parameters at once,
/// and arbitrary system parameters (like [`EventWriter`](crate::event::EventWriter)) can be conveniently fetched.
Expand All @@ -73,6 +75,8 @@ impl SystemMeta {
/// - [`Local`](crate::system::Local) variables that hold state
/// - [`EventReader`](crate::event::EventReader) system parameters, which rely on a [`Local`](crate::system::Local) to track which events have been seen
///
/// Note that this is automatically handled for you when using a [`SystemRegistry`](crate::system::SystemRegistry).
///
/// # Example
///
/// Basic usage:
Expand Down Expand Up @@ -444,14 +448,27 @@ where
self.system_meta.name.as_ref(),
);
}

#[inline]
fn default_labels(&self) -> Vec<Box<dyn SystemLabel>> {
vec![Box::new(self.func.as_system_label())]
}
}

/// A [`SystemLabel`] that was automatically generated for a system on the basis of its `TypeId`.
#[derive(Default)]
pub struct SystemTypeIdLabel<T: 'static>(PhantomData<fn() -> T>);

impl<T: 'static> SystemTypeIdLabel<T> {
/// Constructs a new copy of the [`SystemTypeIdLabel`] for the type `T`
///
/// You can also construct this by using [`.as_system_label()`](crate::system::AsSystemLabel) on a concrete instance
/// of your function type.
pub fn new() -> Self {
Self(PhantomData::default())
}
}

impl<T> Debug for SystemTypeIdLabel<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("SystemTypeIdLabel")
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_ecs/src/system/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ mod query;
mod system;
mod system_chaining;
mod system_param;
mod system_registry;

pub use commands::*;
pub use exclusive_system::*;
Expand All @@ -82,6 +83,7 @@ pub use query::*;
pub use system::*;
pub use system_chaining::*;
pub use system_param::*;
pub use system_registry::*;

/// Ensure that a given function is a system
///
Expand Down
Loading