Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/system/commands/parallel_scope.rs
6609 views
1
use bevy_utils::Parallel;
2
3
use crate::{
4
entity::Entities,
5
prelude::World,
6
system::{Deferred, SystemBuffer, SystemMeta, SystemParam},
7
};
8
9
use super::{CommandQueue, Commands};
10
11
#[derive(Default)]
12
struct ParallelCommandQueue {
13
thread_queues: Parallel<CommandQueue>,
14
}
15
16
/// An alternative to [`Commands`] that can be used in parallel contexts, such as those
17
/// in [`Query::par_iter`](crate::system::Query::par_iter).
18
///
19
/// For cases where multiple non-computation-heavy (lightweight) bundles of the same
20
/// [`Bundle`](crate::prelude::Bundle) type need to be spawned, consider using
21
/// [`Commands::spawn_batch`] for better performance.
22
///
23
/// # Note
24
///
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
/// # Example
29
///
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: ParallelCommands
40
/// ) {
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)]
52
pub struct ParallelCommands<'w, 's> {
53
state: Deferred<'s, ParallelCommandQueue>,
54
entities: &'w Entities,
55
}
56
57
impl SystemBuffer for ParallelCommandQueue {
58
#[inline]
59
fn apply(&mut self, _system_meta: &SystemMeta, world: &mut World) {
60
#[cfg(feature = "trace")]
61
let _system_span = _system_meta.commands_span.enter();
62
for cq in self.thread_queues.iter_mut() {
63
cq.apply(world);
64
}
65
}
66
}
67
68
impl<'w, 's> ParallelCommands<'w, 's> {
69
/// Temporarily provides access to the [`Commands`] for the current thread.
70
///
71
/// For an example, see the type-level documentation for [`ParallelCommands`].
72
pub fn command_scope<R>(&self, f: impl FnOnce(Commands) -> R) -> R {
73
self.state.thread_queues.scope(|queue| {
74
let commands = Commands::new_from_entities(queue, self.entities);
75
f(commands)
76
})
77
}
78
}
79
80