Path: blob/main/crates/bevy_ecs/src/system/commands/parallel_scope.rs
9371 views
use bevy_utils::Parallel;12use crate::{3entity::{Entities, EntityAllocator},4prelude::World,5system::{Deferred, SystemBuffer, SystemMeta, SystemParam},6world::DeferredWorld,7};89use super::{CommandQueue, Commands};1011#[derive(Default)]12struct ParallelCommandQueue {13thread_queues: Parallel<CommandQueue>,14}1516/// An alternative to [`Commands`] that can be used in parallel contexts, such as those17/// in [`Query::par_iter`](crate::system::Query::par_iter).18///19/// For cases where multiple non-computation-heavy (lightweight) bundles of the same20/// [`Bundle`](crate::prelude::Bundle) type need to be spawned, consider using21/// [`Commands::spawn_batch`] for better performance.22///23/// # Note24///25/// Because command application order will depend on how many threads are ran,26/// non-commutative commands may result in non-deterministic results.27///28/// # Example29///30/// ```31/// # use bevy_ecs::prelude::*;32/// # use bevy_tasks::ComputeTaskPool;33/// #34/// # #[derive(Component)]35/// # struct Velocity;36/// # impl Velocity { fn magnitude(&self) -> f32 { 42.0 } }37/// fn parallel_command_system(38/// mut query: Query<(Entity, &Velocity)>,39/// par_commands: ParallelCommands40/// ) {41/// query.par_iter().for_each(|(entity, velocity)| {42/// if velocity.magnitude() > 10.0 {43/// par_commands.command_scope(|mut commands| {44/// commands.entity(entity).despawn();45/// });46/// }47/// });48/// }49/// # bevy_ecs::system::assert_is_system(parallel_command_system);50/// ```51#[derive(SystemParam)]52pub struct ParallelCommands<'w, 's> {53state: Deferred<'s, ParallelCommandQueue>,54allocator: &'w EntityAllocator,55entities: &'w Entities,56}5758impl SystemBuffer for ParallelCommandQueue {59#[inline]60fn apply(&mut self, _system_meta: &SystemMeta, world: &mut World) {61#[cfg(feature = "trace")]62let _system_span = _system_meta.commands_span.enter();63for cq in self.thread_queues.iter_mut() {64cq.apply(world);65}66}6768#[inline]69fn queue(&mut self, _system_meta: &SystemMeta, mut world: DeferredWorld) {70#[cfg(feature = "trace")]71let _system_span = _system_meta.commands_span.enter();72for cq in self.thread_queues.iter_mut() {73world.commands().append(cq);74}75}76}7778impl<'w, 's> ParallelCommands<'w, 's> {79/// Temporarily provides access to the [`Commands`] for the current thread.80///81/// For an example, see the type-level documentation for [`ParallelCommands`].82pub fn command_scope<R>(&self, f: impl FnOnce(Commands) -> R) -> R {83self.state.thread_queues.scope(|queue| {84let commands = Commands::new_from_entities(queue, self.allocator, self.entities);85f(commands)86})87}88}899091