Skip to content

Commit 23e6ddf

Browse files
committed
move all logic to UnsafeWorldCell
1 parent e5b5220 commit 23e6ddf

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]
@@ -603,19 +621,10 @@ impl<'w> EntityMut<'w> {
603621
/// which is only valid while the [`EntityMut`] is alive.
604622
#[inline]
605623
pub fn get_by_id(&self, component_id: ComponentId) -> Option<Ptr<'_>> {
606-
let info = self.world.components().get_info(component_id)?;
607624
// SAFETY:
608-
// - entity_location is valid
609-
// - component_id is valid as checked by the line above
610-
// - the storage type is accurate as checked by the fetched ComponentInfo
611-
unsafe {
612-
self.world.get_component(
613-
component_id,
614-
info.storage_type(),
615-
self.entity,
616-
self.location,
617-
)
618-
}
625+
// - `&self` ensures that no mutable references exist to this entity's components.
626+
// - `as_unsafe_world_cell_readonly` gives read only permission for all components on this entity
627+
unsafe { self.as_unsafe_world_cell_readonly().get_by_id(component_id) }
619628
}
620629

621630
/// Gets a [`MutUntyped`] of the component of the given [`ComponentId`] from the entity.
@@ -628,32 +637,13 @@ impl<'w> EntityMut<'w> {
628637
/// which is only valid while the [`EntityMut`] is alive.
629638
#[inline]
630639
pub fn get_mut_by_id(&mut self, component_id: ComponentId) -> Option<MutUntyped<'_>> {
631-
self.world.components().get_info(component_id)?;
632-
// SAFETY: entity_location is valid, component_id is valid as checked by the line above
633-
unsafe { get_mut_by_id(self.world, self.entity, self.location, component_id) }
634-
}
635-
}
636-
637-
pub(crate) fn contains_component_with_type(
638-
world: &World,
639-
type_id: TypeId,
640-
location: EntityLocation,
641-
) -> bool {
642-
if let Some(component_id) = world.components.get_id(type_id) {
643-
contains_component_with_id(world, component_id, location)
644-
} else {
645-
false
640+
// SAFETY:
641+
// - `&mut self` ensures that no references exist to this entity's components.
642+
// - `as_unsafe_world_cell` gives mutable permission for all components on this entity
643+
unsafe { self.as_unsafe_world_cell().get_mut_by_id(component_id) }
646644
}
647645
}
648646

649-
pub(crate) fn contains_component_with_id(
650-
world: &World,
651-
component_id: ComponentId,
652-
location: EntityLocation,
653-
) -> bool {
654-
world.archetypes[location.archetype_id].contains(component_id)
655-
}
656-
657647
/// Removes a bundle from the given archetype and returns the resulting archetype (or None if the
658648
/// removal was invalid). in the event that adding the given bundle does not result in an Archetype
659649
/// change. Results are cached in the Archetype Graph to avoid redundant work.
@@ -771,59 +761,6 @@ fn sorted_remove<T: Eq + Ord + Copy>(source: &mut Vec<T>, remove: &[T]) {
771761
});
772762
}
773763

774-
// SAFETY: EntityLocation must be valid
775-
#[inline]
776-
pub(crate) unsafe fn get_mut<T: Component>(
777-
world: &mut World,
778-
entity: Entity,
779-
location: EntityLocation,
780-
) -> Option<Mut<'_, T>> {
781-
let change_tick = world.change_tick();
782-
let last_change_tick = world.last_change_tick();
783-
// SAFETY:
784-
// - world access is unique
785-
// - entity location is valid
786-
// - returned component is of type T
787-
world
788-
.get_component_and_ticks_with_type(
789-
TypeId::of::<T>(),
790-
T::Storage::STORAGE_TYPE,
791-
entity,
792-
location,
793-
)
794-
.map(|(value, ticks)| Mut {
795-
// SAFETY:
796-
// - world access is unique and ties world lifetime to `Mut` lifetime
797-
// - `value` is of type `T`
798-
value: value.assert_unique().deref_mut::<T>(),
799-
ticks: TicksMut::from_tick_cells(ticks, last_change_tick, change_tick),
800-
})
801-
}
802-
803-
// SAFETY: EntityLocation must be valid, component_id must be valid
804-
#[inline]
805-
pub(crate) unsafe fn get_mut_by_id(
806-
world: &mut World,
807-
entity: Entity,
808-
location: EntityLocation,
809-
component_id: ComponentId,
810-
) -> Option<MutUntyped<'_>> {
811-
let change_tick = world.change_tick();
812-
// SAFETY: component_id is valid
813-
let info = world.components.get_info_unchecked(component_id);
814-
// SAFETY:
815-
// - world access is unique
816-
// - entity location is valid
817-
// - returned component is of type T
818-
world
819-
.get_component_and_ticks(component_id, info.storage_type(), entity, location)
820-
.map(|(value, ticks)| MutUntyped {
821-
// SAFETY: world access is unique and ties world lifetime to `MutUntyped` lifetime
822-
value: value.assert_unique(),
823-
ticks: TicksMut::from_tick_cells(ticks, world.last_change_tick(), change_tick),
824-
})
825-
}
826-
827764
/// Moves component data out of storage.
828765
///
829766
/// This function leaves the underlying memory unchanged, but the component behind

0 commit comments

Comments
 (0)