Struct bevy_ecs::world::unsafe_world_cell::UnsafeWorldCell
source · pub struct UnsafeWorldCell<'w>(_, _);
Expand description
Variant of the World
where resource and component accesses take &self
, and the responsibility to avoid
aliasing violations are given to the caller instead of being checked at compile-time by rust’s unique XOR shared rule.
Rationale
In rust, having a &mut World
means that there are absolutely no other references to the safe world alive at the same time,
without exceptions. Not even unsafe code can change this.
But there are situations where careful shared mutable access through a type is possible and safe. For this, rust provides the UnsafeCell
escape hatch, which allows you to get a *mut T
from a &UnsafeCell<T>
and around which safe abstractions can be built.
Access to resources and components can be done uniquely using World::resource_mut
and World::entity_mut
, and shared using World::resource
and World::entity
.
These methods use lifetimes to check at compile time that no aliasing rules are being broken.
This alone is not enough to implement bevy systems where multiple systems can access disjoint parts of the world concurrently. For this, bevy stores all values of
resources and components (and ComponentTicks
) in UnsafeCell
s, and carefully validates disjoint access patterns using
APIs like System::component_access
.
A system then can be executed using System::run_unsafe
with a &World
and use methods with interior mutability to access resource values.
access resource values.
Example Usage
UnsafeWorldCell
can be used as a building block for writing APIs that safely allow disjoint access into the world.
In the following example, the world is split into a resource access half and a component access half, where each one can
safely hand out mutable references.
use bevy_ecs::world::World;
use bevy_ecs::change_detection::Mut;
use bevy_ecs::system::Resource;
use bevy_ecs::world::unsafe_world_cell::UnsafeWorldCell;
// INVARIANT: existence of this struct means that users of it are the only ones being able to access resources in the world
struct OnlyResourceAccessWorld<'w>(UnsafeWorldCell<'w>);
// INVARIANT: existence of this struct means that users of it are the only ones being able to access components in the world
struct OnlyComponentAccessWorld<'w>(UnsafeWorldCell<'w>);
impl<'w> OnlyResourceAccessWorld<'w> {
fn get_resource_mut<T: Resource>(&mut self) -> Option<Mut<'w, T>> {
// SAFETY: resource access is allowed through this UnsafeWorldCell
unsafe { self.0.get_resource_mut::<T>() }
}
}
// impl<'w> OnlyComponentAccessWorld<'w> {
// ...
// }
// the two `UnsafeWorldCell`s borrow from the `&mut World`, so it cannot be accessed while they are live
fn split_world_access(world: &mut World) -> (OnlyResourceAccessWorld<'_>, OnlyComponentAccessWorld<'_>) {
let unsafe_world_cell = world.as_unsafe_world_cell();
let resource_access = OnlyResourceAccessWorld(unsafe_world_cell);
let component_access = OnlyComponentAccessWorld(unsafe_world_cell);
(resource_access, component_access)
}
Implementations§
source§impl<'w> UnsafeWorldCell<'w>
impl<'w> UnsafeWorldCell<'w>
sourcepub unsafe fn world_mut(self) -> &'w mut World
pub unsafe fn world_mut(self) -> &'w mut World
This &mut World
counts as a mutable borrow of every resource and component for the purposes
of safety invariants that talk about borrows on component/resource data not existing. This is
true even for methods that do not explicitly call out &mut World
as problematic.
Safety
- must have permission to access everything mutably
- there must be no other borrows on world
- returned borrow must not be used in any way if the world is accessed
through other means than the
&mut World
after this call.
sourcepub unsafe fn world(self) -> &'w World
pub unsafe fn world(self) -> &'w World
Gets a reference to the &World
this UnsafeWorldCell
belongs to.
This can be used for arbitrary shared/readonly access.
Safety
- must have permission to access the whole world immutably
- there must be no live exclusive borrows on world data
- there must be no live exclusive borrow of world
sourcepub unsafe fn world_metadata(self) -> &'w World
pub unsafe fn world_metadata(self) -> &'w World
Gets a reference to the World
this UnsafeWorldCell
belong to.
This can be used for arbitrary read only access of world metadata
You should attempt to use various safe methods on UnsafeWorldCell
for
metadata access before using this method.
Safety
- must only be used to access world metadata
sourcepub fn archetypes(self) -> &'w Archetypes
pub fn archetypes(self) -> &'w Archetypes
Retrieves this world’s Archetypes collection
sourcepub fn components(self) -> &'w Components
pub fn components(self) -> &'w Components
Retrieves this world’s Components collection
sourcepub fn read_change_tick(self) -> u32
pub fn read_change_tick(self) -> u32
Reads the current change tick of this world.
pub fn last_change_tick(self) -> u32
pub fn increment_change_tick(self) -> u32
sourcepub fn get_entity(self, entity: Entity) -> Option<UnsafeEntityCell<'w>>
pub fn get_entity(self, entity: Entity) -> Option<UnsafeEntityCell<'w>>
Retrieves an UnsafeEntityCell
that exposes read and write operations for the given entity
.
Similar to the UnsafeWorldCell
, you are in charge of making sure that no aliasing rules are violated.
sourcepub unsafe fn get_resource<R: Resource>(self) -> Option<&'w R>
pub unsafe fn get_resource<R: Resource>(self) -> Option<&'w R>
Gets a reference to the resource of the given type if it exists
Safety
It is the callers responsibility to ensure that
- the
UnsafeWorldCell
has permission to access the resource - no mutable reference to the resource exists at the same time
sourcepub unsafe fn get_resource_by_id(
self,
component_id: ComponentId
) -> Option<Ptr<'w>>
pub unsafe fn get_resource_by_id( self, component_id: ComponentId ) -> Option<Ptr<'w>>
Gets a pointer to the resource with the id ComponentId
if it exists.
The returned pointer must not be used to modify the resource, and must not be
dereferenced after the borrow of the World
ends.
You should prefer to use the typed API UnsafeWorldCell::get_resource
where possible and only
use this in cases where the actual types are not known at compile time.
Safety
It is the callers responsibility to ensure that
- the
UnsafeWorldCell
has permission to access the resource - no mutable reference to the resource exists at the same time
sourcepub unsafe fn get_non_send_resource<R: 'static>(self) -> Option<&'w R>
pub unsafe fn get_non_send_resource<R: 'static>(self) -> Option<&'w R>
Gets a reference to the non-send resource of the given type if it exists
Safety
It is the callers responsibility to ensure that
- the
UnsafeWorldCell
has permission to access the resource - no mutable reference to the resource exists at the same time
sourcepub unsafe fn get_non_send_resource_by_id(
self,
component_id: ComponentId
) -> Option<Ptr<'w>>
pub unsafe fn get_non_send_resource_by_id( self, component_id: ComponentId ) -> Option<Ptr<'w>>
Gets a !Send
resource to the resource with the id ComponentId
if it exists.
The returned pointer must not be used to modify the resource, and must not be
dereferenced after the immutable borrow of the World
ends.
You should prefer to use the typed API UnsafeWorldCell::get_non_send_resource
where possible and only
use this in cases where the actual types are not known at compile time.
Panics
This function will panic if it isn’t called from the same thread that the resource was inserted from.
Safety
It is the callers responsibility to ensure that
- the
UnsafeWorldCell
has permission to access the resource - no mutable reference to the resource exists at the same time
sourcepub unsafe fn get_resource_mut<R: Resource>(self) -> Option<Mut<'w, R>>
pub unsafe fn get_resource_mut<R: Resource>(self) -> Option<Mut<'w, R>>
Gets a mutable reference to the resource of the given type if it exists
Safety
It is the callers responsibility to ensure that
- the
UnsafeWorldCell
has permission to access the resource mutably - no other references to the resource exist at the same time
sourcepub unsafe fn get_resource_mut_by_id(
self,
component_id: ComponentId
) -> Option<MutUntyped<'w>>
pub unsafe fn get_resource_mut_by_id( self, component_id: ComponentId ) -> Option<MutUntyped<'w>>
Gets a pointer to the resource with the id ComponentId
if it exists.
The returned pointer may be used to modify the resource, as long as the mutable borrow
of the UnsafeWorldCell
is still valid.
You should prefer to use the typed API UnsafeWorldCell::get_resource_mut
where possible and only
use this in cases where the actual types are not known at compile time.
Safety
It is the callers responsibility to ensure that
- the
UnsafeWorldCell
has permission to access the resource mutably - no other references to the resource exist at the same time
sourcepub unsafe fn get_non_send_resource_mut<R: 'static>(self) -> Option<Mut<'w, R>>
pub unsafe fn get_non_send_resource_mut<R: 'static>(self) -> Option<Mut<'w, R>>
Gets a mutable reference to the non-send resource of the given type if it exists
Safety
It is the callers responsibility to ensure that
- the
UnsafeWorldCell
has permission to access the resource mutably - no other references to the resource exist at the same time
sourcepub unsafe fn get_non_send_resource_mut_by_id(
self,
component_id: ComponentId
) -> Option<MutUntyped<'w>>
pub unsafe fn get_non_send_resource_mut_by_id( self, component_id: ComponentId ) -> Option<MutUntyped<'w>>
Gets a !Send
resource to the resource with the id ComponentId
if it exists.
The returned pointer may be used to modify the resource, as long as the mutable borrow
of the World
is still valid.
You should prefer to use the typed API UnsafeWorldCell::get_non_send_resource_mut
where possible and only
use this in cases where the actual types are not known at compile time.
Panics
This function will panic if it isn’t called from the same thread that the resource was inserted from.
Safety
It is the callers responsibility to ensure that
- the
UnsafeWorldCell
has permission to access the resource mutably - no other references to the resource exist at the same time
Trait Implementations§
source§impl<'w> Clone for UnsafeWorldCell<'w>
impl<'w> Clone for UnsafeWorldCell<'w>
source§fn clone(&self) -> UnsafeWorldCell<'w>
fn clone(&self) -> UnsafeWorldCell<'w>
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moreimpl<'w> Copy for UnsafeWorldCell<'w>
impl Send for UnsafeWorldCell<'_>
impl Sync for UnsafeWorldCell<'_>
Auto Trait Implementations§
impl<'w> !RefUnwindSafe for UnsafeWorldCell<'w>
impl<'w> Unpin for UnsafeWorldCell<'w>
impl<'w> !UnwindSafe for UnsafeWorldCell<'w>
Blanket Implementations§
source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere T: Any,
source§fn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>
fn into_any(self: Box<T, Global>) -> Box<dyn Any + 'static, Global>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any + 'static>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any + 'static>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.