Skip to content

Commit dda503e

Browse files
committed
move all logic to UnsafeWorldCell
1 parent 0cb0d8b commit dda503e

File tree

5 files changed

+602
-537
lines changed

5 files changed

+602
-537
lines changed

crates/bevy_ecs/src/system/system_param.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,7 @@ unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> {
448448
change_tick: u32,
449449
) -> Self::Item<'w, 's> {
450450
let (ptr, ticks) = world
451+
.as_unsafe_world_cell_migration_internal()
451452
.get_resource_with_ticks(component_id)
452453
.unwrap_or_else(|| {
453454
panic!(
@@ -488,6 +489,7 @@ unsafe impl<'a, T: Resource> SystemParam for Option<Res<'a, T>> {
488489
change_tick: u32,
489490
) -> Self::Item<'w, 's> {
490491
world
492+
.as_unsafe_world_cell_migration_internal()
491493
.get_resource_with_ticks(component_id)
492494
.map(|(ptr, ticks)| Res {
493495
value: ptr.deref(),
@@ -542,7 +544,7 @@ unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
542544
) -> Self::Item<'w, 's> {
543545
let value = world
544546
.as_unsafe_world_cell_migration_internal()
545-
.get_resource_mut_with_id(component_id)
547+
.get_resource_mut_by_id(component_id)
546548
.unwrap_or_else(|| {
547549
panic!(
548550
"Resource requested by {} does not exist: {}",
@@ -551,7 +553,7 @@ unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
551553
)
552554
});
553555
ResMut {
554-
value: value.value,
556+
value: value.value.deref_mut::<T>(),
555557
ticks: TicksMut {
556558
added: value.ticks.added,
557559
changed: value.ticks.changed,
@@ -580,9 +582,9 @@ unsafe impl<'a, T: Resource> SystemParam for Option<ResMut<'a, T>> {
580582
) -> Self::Item<'w, 's> {
581583
world
582584
.as_unsafe_world_cell_migration_internal()
583-
.get_resource_mut_with_id(component_id)
585+
.get_resource_mut_by_id(component_id)
584586
.map(|value| ResMut {
585-
value: value.value,
587+
value: value.value.deref_mut::<T>(),
586588
ticks: TicksMut {
587589
added: value.ticks.added,
588590
changed: value.ticks.changed,
@@ -974,6 +976,7 @@ unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> {
974976
change_tick: u32,
975977
) -> Self::Item<'w, 's> {
976978
let (ptr, ticks) = world
979+
.as_unsafe_world_cell_migration_internal()
977980
.get_non_send_with_ticks(component_id)
978981
.unwrap_or_else(|| {
979982
panic!(
@@ -1012,6 +1015,7 @@ unsafe impl<T: 'static> SystemParam for Option<NonSend<'_, T>> {
10121015
change_tick: u32,
10131016
) -> Self::Item<'w, 's> {
10141017
world
1018+
.as_unsafe_world_cell_migration_internal()
10151019
.get_non_send_with_ticks(component_id)
10161020
.map(|(ptr, ticks)| NonSend {
10171021
value: ptr.deref(),
@@ -1064,6 +1068,7 @@ unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
10641068
change_tick: u32,
10651069
) -> Self::Item<'w, 's> {
10661070
let (ptr, ticks) = world
1071+
.as_unsafe_world_cell_migration_internal()
10671072
.get_non_send_with_ticks(component_id)
10681073
.unwrap_or_else(|| {
10691074
panic!(
@@ -1096,6 +1101,7 @@ unsafe impl<'a, T: 'static> SystemParam for Option<NonSendMut<'a, T>> {
10961101
change_tick: u32,
10971102
) -> Self::Item<'w, 's> {
10981103
world
1104+
.as_unsafe_world_cell_migration_internal()
10991105
.get_non_send_with_ticks(component_id)
11001106
.map(|(ptr, ticks)| NonSendMut {
11011107
value: ptr.assert_unique().deref_mut(),

crates/bevy_ecs/src/world/entity_ref.rs

Lines changed: 33 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
use crate::{
22
archetype::{Archetype, ArchetypeId, Archetypes},
33
bundle::{Bundle, BundleInfo},
4-
change_detection::{MutUntyped, TicksMut},
5-
component::{
6-
Component, ComponentId, ComponentStorage, ComponentTicks, Components, StorageType,
7-
},
4+
change_detection::MutUntyped,
5+
component::{Component, ComponentId, ComponentTicks, Components, StorageType},
86
entity::{Entities, Entity, EntityLocation},
97
storage::{SparseSet, Storages},
108
world::{Mut, World},
@@ -78,12 +76,22 @@ impl<'w> EntityRef<'w> {
7876

7977
#[inline]
8078
pub fn contains_id(&self, component_id: ComponentId) -> bool {
81-
contains_component_with_id(self.world, component_id, self.location)
79+
// SAFETY:
80+
// - `EntityRef` existing requires there not to be a `&mut World`
81+
unsafe {
82+
self.as_unsafe_world_cell_readonly()
83+
.contains_id(component_id)
84+
}
8285
}
8386

8487
#[inline]
8588
pub fn contains_type_id(&self, type_id: TypeId) -> bool {
86-
contains_component_with_type(self.world, type_id, self.location)
89+
// SAFETY:
90+
// - `EntityRef` existing requires there not to be a `&mut World`
91+
unsafe {
92+
self.as_unsafe_world_cell_readonly()
93+
.contains_type_id(type_id)
94+
}
8795
}
8896

8997
#[inline]
@@ -208,12 +216,22 @@ impl<'w> EntityMut<'w> {
208216

209217
#[inline]
210218
pub fn contains_id(&self, component_id: ComponentId) -> bool {
211-
contains_component_with_id(self.world, component_id, self.location)
219+
// SAFETY:
220+
// - `EntityMut` has exclusive access on world so noone else can have a `&mut World`
221+
unsafe {
222+
self.as_unsafe_world_cell_readonly()
223+
.contains_id(component_id)
224+
}
212225
}
213226

214227
#[inline]
215228
pub fn contains_type_id(&self, type_id: TypeId) -> bool {
216-
contains_component_with_type(self.world, type_id, self.location)
229+
// SAFETY:
230+
// - `EntityMut` has exclusive access on world so noone else can have a `&mut World`
231+
unsafe {
232+
self.as_unsafe_world_cell_readonly()
233+
.contains_type_id(type_id)
234+
}
217235
}
218236

219237
#[inline]
@@ -564,19 +582,10 @@ impl<'w> EntityMut<'w> {
564582
/// which is only valid while the [`EntityMut`] is alive.
565583
#[inline]
566584
pub fn get_by_id(&self, component_id: ComponentId) -> Option<Ptr<'_>> {
567-
let info = self.world.components().get_info(component_id)?;
568585
// SAFETY:
569-
// - entity_location is valid
570-
// - component_id is valid as checked by the line above
571-
// - the storage type is accurate as checked by the fetched ComponentInfo
572-
unsafe {
573-
self.world.get_component(
574-
component_id,
575-
info.storage_type(),
576-
self.entity,
577-
self.location,
578-
)
579-
}
586+
// - `&self` ensures that no mutable references exist to this entity's components.
587+
// - `as_unsafe_world_cell_readonly` gives read only permission for all components on this entity
588+
unsafe { self.as_unsafe_world_cell_readonly().get_by_id(component_id) }
580589
}
581590

582591
/// Gets a [`MutUntyped`] of the component of the given [`ComponentId`] from the entity.
@@ -589,32 +598,13 @@ impl<'w> EntityMut<'w> {
589598
/// which is only valid while the [`EntityMut`] is alive.
590599
#[inline]
591600
pub fn get_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
592-
self.world.components().get_info(component_id)?;
593-
// SAFETY: entity_location is valid, component_id is valid as checked by the line above
594-
unsafe { get_mut_by_id(self.world, self.entity, self.location, component_id) }
595-
}
596-
}
597-
598-
pub(crate) fn contains_component_with_type(
599-
world: &World,
600-
type_id: TypeId,
601-
location: EntityLocation,
602-
) -> bool {
603-
if let Some(component_id) = world.components.get_id(type_id) {
604-
contains_component_with_id(world, component_id, location)
605-
} else {
606-
false
601+
// SAFETY:
602+
// - `&mut self` ensures that no references exist to this entity's components.
603+
// - `as_unsafe_world_cell` gives mutable permission for all components on this entity
604+
unsafe { self.as_unsafe_world_cell().get_mut_by_id(component_id) }
607605
}
608606
}
609607

610-
pub(crate) fn contains_component_with_id(
611-
world: &World,
612-
component_id: ComponentId,
613-
location: EntityLocation,
614-
) -> bool {
615-
world.archetypes[location.archetype_id].contains(component_id)
616-
}
617-
618608
/// Removes a bundle from the given archetype and returns the resulting archetype (or None if the
619609
/// removal was invalid). in the event that adding the given bundle does not result in an Archetype
620610
/// change. Results are cached in the Archetype Graph to avoid redundant work.
@@ -732,59 +722,6 @@ fn sorted_remove<T: Eq + Ord + Copy>(source: &mut Vec<T>, remove: &[T]) {
732722
});
733723
}
734724

735-
// SAFETY: EntityLocation must be valid
736-
#[inline]
737-
pub(crate) unsafe fn get_mut<T: Component>(
738-
world: &mut World,
739-
entity: Entity,
740-
location: EntityLocation,
741-
) -> Option<Mut<'_, T>> {
742-
let change_tick = world.change_tick();
743-
let last_change_tick = world.last_change_tick();
744-
// SAFETY:
745-
// - world access is unique
746-
// - entity location is valid
747-
// - returned component is of type T
748-
world
749-
.get_component_and_ticks_with_type(
750-
TypeId::of::<T>(),
751-
T::Storage::STORAGE_TYPE,
752-
entity,
753-
location,
754-
)
755-
.map(|(value, ticks)| Mut {
756-
// SAFETY:
757-
// - world access is unique and ties world lifetime to `Mut` lifetime
758-
// - `value` is of type `T`
759-
value: value.assert_unique().deref_mut::<T>(),
760-
ticks: TicksMut::from_tick_cells(ticks, last_change_tick, change_tick),
761-
})
762-
}
763-
764-
// SAFETY: EntityLocation must be valid, component_id must be valid
765-
#[inline]
766-
pub(crate) unsafe fn get_mut_by_id(
767-
world: &mut World,
768-
entity: Entity,
769-
location: EntityLocation,
770-
component_id: ComponentId,
771-
) -> Option<MutUntyped<'_>> {
772-
let change_tick = world.change_tick();
773-
// SAFETY: component_id is valid
774-
let info = world.components.get_info_unchecked(component_id);
775-
// SAFETY:
776-
// - world access is unique
777-
// - entity location is valid
778-
// - returned component is of type T
779-
world
780-
.get_component_and_ticks(component_id, info.storage_type(), entity, location)
781-
.map(|(value, ticks)| MutUntyped {
782-
// SAFETY: world access is unique and ties world lifetime to `MutUntyped` lifetime
783-
value: value.assert_unique(),
784-
ticks: TicksMut::from_tick_cells(ticks, world.last_change_tick(), change_tick),
785-
})
786-
}
787-
788725
/// Moves component data out of storage.
789726
///
790727
/// This function leaves the underlying memory unchanged, but the component behind

0 commit comments

Comments
 (0)