Path: blob/main/crates/bevy_ecs/src/system/commands/parallel_scope.rs
6609 views
use bevy_utils::Parallel;12use crate::{3entity::Entities,4prelude::World,5system::{Deferred, SystemBuffer, SystemMeta, SystemParam},6};78use super::{CommandQueue, Commands};910#[derive(Default)]11struct ParallelCommandQueue {12thread_queues: Parallel<CommandQueue>,13}1415/// An alternative to [`Commands`] that can be used in parallel contexts, such as those16/// in [`Query::par_iter`](crate::system::Query::par_iter).17///18/// For cases where multiple non-computation-heavy (lightweight) bundles of the same19/// [`Bundle`](crate::prelude::Bundle) type need to be spawned, consider using20/// [`Commands::spawn_batch`] for better performance.21///22/// # Note23///24/// Because command application order will depend on how many threads are ran,25/// non-commutative commands may result in non-deterministic results.26///27/// # Example28///29/// ```30/// # use bevy_ecs::prelude::*;31/// # use bevy_tasks::ComputeTaskPool;32/// #33/// # #[derive(Component)]34/// # struct Velocity;35/// # impl Velocity { fn magnitude(&self) -> f32 { 42.0 } }36/// fn parallel_command_system(37/// mut query: Query<(Entity, &Velocity)>,38/// par_commands: ParallelCommands39/// ) {40/// query.par_iter().for_each(|(entity, velocity)| {41/// if velocity.magnitude() > 10.0 {42/// par_commands.command_scope(|mut commands| {43/// commands.entity(entity).despawn();44/// });45/// }46/// });47/// }48/// # bevy_ecs::system::assert_is_system(parallel_command_system);49/// ```50#[derive(SystemParam)]51pub struct ParallelCommands<'w, 's> {52state: Deferred<'s, ParallelCommandQueue>,53entities: &'w Entities,54}5556impl SystemBuffer for ParallelCommandQueue {57#[inline]58fn apply(&mut self, _system_meta: &SystemMeta, world: &mut World) {59#[cfg(feature = "trace")]60let _system_span = _system_meta.commands_span.enter();61for cq in self.thread_queues.iter_mut() {62cq.apply(world);63}64}65}6667impl<'w, 's> ParallelCommands<'w, 's> {68/// Temporarily provides access to the [`Commands`] for the current thread.69///70/// For an example, see the type-level documentation for [`ParallelCommands`].71pub fn command_scope<R>(&self, f: impl FnOnce(Commands) -> R) -> R {72self.state.thread_queues.scope(|queue| {73let commands = Commands::new_from_entities(queue, self.entities);74f(commands)75})76}77}787980