mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Have FilteredResources borrow the Access to avoid cloning.
This commit is contained in:
parent
f131f40bfb
commit
be10dba9ad
3 changed files with 54 additions and 51 deletions
|
@ -364,14 +364,14 @@ impl<'a> FilteredResourcesParamBuilder<Box<dyn FnOnce(&mut FilteredResourcesBuil
|
|||
|
||||
// SAFETY: Resource ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this FilteredResources
|
||||
// conflicts with any prior access, a panic will occur.
|
||||
unsafe impl<'w, T: FnOnce(&mut FilteredResourcesBuilder)> SystemParamBuilder<FilteredResources<'w>>
|
||||
for FilteredResourcesParamBuilder<T>
|
||||
unsafe impl<'w, 's, T: FnOnce(&mut FilteredResourcesBuilder)>
|
||||
SystemParamBuilder<FilteredResources<'w, 's>> for FilteredResourcesParamBuilder<T>
|
||||
{
|
||||
fn build(
|
||||
self,
|
||||
world: &mut World,
|
||||
meta: &mut SystemMeta,
|
||||
) -> <FilteredResources<'w> as SystemParam>::State {
|
||||
) -> <FilteredResources<'w, 's> as SystemParam>::State {
|
||||
let mut builder = FilteredResourcesBuilder::new(world);
|
||||
(self.0)(&mut builder);
|
||||
let access = builder.build();
|
||||
|
@ -427,14 +427,14 @@ impl<'a> FilteredResourcesMutParamBuilder<Box<dyn FnOnce(&mut FilteredResourcesM
|
|||
|
||||
// SAFETY: Resource ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this FilteredResources
|
||||
// conflicts with any prior access, a panic will occur.
|
||||
unsafe impl<'w, T: FnOnce(&mut FilteredResourcesMutBuilder)>
|
||||
SystemParamBuilder<FilteredResourcesMut<'w>> for FilteredResourcesMutParamBuilder<T>
|
||||
unsafe impl<'w, 's, T: FnOnce(&mut FilteredResourcesMutBuilder)>
|
||||
SystemParamBuilder<FilteredResourcesMut<'w, 's>> for FilteredResourcesMutParamBuilder<T>
|
||||
{
|
||||
fn build(
|
||||
self,
|
||||
world: &mut World,
|
||||
meta: &mut SystemMeta,
|
||||
) -> <FilteredResourcesMut<'w> as SystemParam>::State {
|
||||
) -> <FilteredResourcesMut<'w, 's> as SystemParam>::State {
|
||||
let mut builder = FilteredResourcesMutBuilder::new(world);
|
||||
(self.0)(&mut builder);
|
||||
let access = builder.build();
|
||||
|
|
|
@ -2094,10 +2094,10 @@ unsafe impl SystemParam for DynSystemParam<'_, '_> {
|
|||
// SAFETY: When initialized with `init_state`, `get_param` returns a `FilteredResources` with no access.
|
||||
// Therefore, `init_state` trivially registers all access, and no accesses can conflict.
|
||||
// Note that the safety requirements for non-empty access are handled by the `SystemParamBuilder` impl that builds them.
|
||||
unsafe impl SystemParam for FilteredResources<'_> {
|
||||
unsafe impl SystemParam for FilteredResources<'_, '_> {
|
||||
type State = Access<ComponentId>;
|
||||
|
||||
type Item<'world, 'state> = FilteredResources<'world>;
|
||||
type Item<'world, 'state> = FilteredResources<'world, 'state>;
|
||||
|
||||
fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {
|
||||
Access::new()
|
||||
|
@ -2109,23 +2109,22 @@ unsafe impl SystemParam for FilteredResources<'_> {
|
|||
world: UnsafeWorldCell<'world>,
|
||||
change_tick: Tick,
|
||||
) -> Self::Item<'world, 'state> {
|
||||
let access = state.clone();
|
||||
// SAFETY: The caller ensures that `world` has access to anything registered in `init_state` or `build`,
|
||||
// and the builder registers `access` in `build`.
|
||||
unsafe { FilteredResources::new(world, access, system_meta.last_run, change_tick) }
|
||||
unsafe { FilteredResources::new(world, state, system_meta.last_run, change_tick) }
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: FilteredResources only reads resources.
|
||||
unsafe impl ReadOnlySystemParam for FilteredResources<'_> {}
|
||||
unsafe impl ReadOnlySystemParam for FilteredResources<'_, '_> {}
|
||||
|
||||
// SAFETY: When initialized with `init_state`, `get_param` returns a `FilteredResourcesMut` with no access.
|
||||
// Therefore, `init_state` trivially registers all access, and no accesses can conflict.
|
||||
// Note that the safety requirements for non-empty access are handled by the `SystemParamBuilder` impl that builds them.
|
||||
unsafe impl SystemParam for FilteredResourcesMut<'_> {
|
||||
unsafe impl SystemParam for FilteredResourcesMut<'_, '_> {
|
||||
type State = Access<ComponentId>;
|
||||
|
||||
type Item<'world, 'state> = FilteredResourcesMut<'world>;
|
||||
type Item<'world, 'state> = FilteredResourcesMut<'world, 'state>;
|
||||
|
||||
fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {
|
||||
Access::new()
|
||||
|
@ -2137,10 +2136,9 @@ unsafe impl SystemParam for FilteredResourcesMut<'_> {
|
|||
world: UnsafeWorldCell<'world>,
|
||||
change_tick: Tick,
|
||||
) -> Self::Item<'world, 'state> {
|
||||
let access = state.clone();
|
||||
// SAFETY: The caller ensures that `world` has access to anything registered in `init_state` or `build`,
|
||||
// and the builder registers `access` in `build`.
|
||||
unsafe { FilteredResourcesMut::new(world, access, system_meta.last_run, change_tick) }
|
||||
unsafe { FilteredResourcesMut::new(world, state, system_meta.last_run, change_tick) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::sync::OnceLock;
|
||||
|
||||
use crate::{
|
||||
change_detection::{MutUntyped, Res, Ticks, TicksMut},
|
||||
component::{ComponentId, Tick},
|
||||
|
@ -115,21 +117,21 @@ use bevy_ptr::UnsafeCellDeref;
|
|||
/// #
|
||||
/// # world.run_system_once(system);
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
pub struct FilteredResources<'w> {
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct FilteredResources<'w, 's> {
|
||||
world: UnsafeWorldCell<'w>,
|
||||
access: Access<ComponentId>,
|
||||
access: &'s Access<ComponentId>,
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
}
|
||||
|
||||
impl<'w> FilteredResources<'w> {
|
||||
impl<'w, 's> FilteredResources<'w, 's> {
|
||||
/// Creates a new [`FilteredResources`].
|
||||
/// # Safety
|
||||
/// It is the callers responsibility to ensure that nothing else may access the any resources in the `world` in a way that conflicts with `access`.
|
||||
pub(crate) unsafe fn new(
|
||||
world: UnsafeWorldCell<'w>,
|
||||
access: Access<ComponentId>,
|
||||
access: &'s Access<ComponentId>,
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
) -> Self {
|
||||
|
@ -143,7 +145,7 @@ impl<'w> FilteredResources<'w> {
|
|||
|
||||
/// Returns a reference to the underlying [`Access`].
|
||||
pub fn access(&self) -> &Access<ComponentId> {
|
||||
&self.access
|
||||
self.access
|
||||
}
|
||||
|
||||
/// Returns `true` if the `FilteredResources` has access to the given resource.
|
||||
|
@ -183,8 +185,8 @@ impl<'w> FilteredResources<'w> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'w> From<FilteredResourcesMut<'w>> for FilteredResources<'w> {
|
||||
fn from(resources: FilteredResourcesMut<'w>) -> Self {
|
||||
impl<'w, 's> From<FilteredResourcesMut<'w, 's>> for FilteredResources<'w, 's> {
|
||||
fn from(resources: FilteredResourcesMut<'w, 's>) -> Self {
|
||||
// SAFETY:
|
||||
// - `FilteredResourcesMut` guarantees exclusive access to all resources in the new `FilteredResources`.
|
||||
unsafe {
|
||||
|
@ -198,14 +200,14 @@ impl<'w> From<FilteredResourcesMut<'w>> for FilteredResources<'w> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a FilteredResourcesMut<'_>> for FilteredResources<'a> {
|
||||
fn from(resources: &'a FilteredResourcesMut<'_>) -> Self {
|
||||
impl<'w, 's> From<&'w FilteredResourcesMut<'_, 's>> for FilteredResources<'w, 's> {
|
||||
fn from(resources: &'w FilteredResourcesMut<'_, 's>) -> Self {
|
||||
// SAFETY:
|
||||
// - `FilteredResourcesMut` guarantees exclusive access to all components in the new `FilteredResources`.
|
||||
unsafe {
|
||||
FilteredResources::new(
|
||||
resources.world,
|
||||
resources.access.clone(),
|
||||
resources.access,
|
||||
resources.last_run,
|
||||
resources.this_run,
|
||||
)
|
||||
|
@ -213,10 +215,15 @@ impl<'a> From<&'a FilteredResourcesMut<'_>> for FilteredResources<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a World> for FilteredResources<'a> {
|
||||
fn from(value: &'a World) -> Self {
|
||||
let mut access = Access::new();
|
||||
access.read_all_resources();
|
||||
impl<'w> From<&'w World> for FilteredResources<'w, 'static> {
|
||||
fn from(value: &'w World) -> Self {
|
||||
static READ_ALL_RESOURCES: OnceLock<Access<ComponentId>> = OnceLock::new();
|
||||
let access = READ_ALL_RESOURCES.get_or_init(|| {
|
||||
let mut access = Access::new();
|
||||
access.read_all_resources();
|
||||
access
|
||||
});
|
||||
|
||||
let last_run = value.last_change_tick();
|
||||
let this_run = value.read_change_tick();
|
||||
// SAFETY: We have a reference to the entire world, so nothing else can alias with read access to all resources.
|
||||
|
@ -231,8 +238,8 @@ impl<'a> From<&'a World> for FilteredResources<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a mut World> for FilteredResources<'a> {
|
||||
fn from(value: &'a mut World) -> Self {
|
||||
impl<'w> From<&'w mut World> for FilteredResources<'w, 'static> {
|
||||
fn from(value: &'w mut World) -> Self {
|
||||
Self::from(&*value)
|
||||
}
|
||||
}
|
||||
|
@ -359,20 +366,20 @@ impl<'a> From<&'a mut World> for FilteredResources<'a> {
|
|||
/// #
|
||||
/// # world.run_system_once(system);
|
||||
/// ```
|
||||
pub struct FilteredResourcesMut<'w> {
|
||||
pub struct FilteredResourcesMut<'w, 's> {
|
||||
world: UnsafeWorldCell<'w>,
|
||||
access: Access<ComponentId>,
|
||||
access: &'s Access<ComponentId>,
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
}
|
||||
|
||||
impl<'w> FilteredResourcesMut<'w> {
|
||||
impl<'w, 's> FilteredResourcesMut<'w, 's> {
|
||||
/// Creates a new [`FilteredResources`].
|
||||
/// # Safety
|
||||
/// It is the callers responsibility to ensure that nothing else may access the any resources in the `world` in a way that conflicts with `access`.
|
||||
pub(crate) unsafe fn new(
|
||||
world: UnsafeWorldCell<'w>,
|
||||
access: Access<ComponentId>,
|
||||
access: &'s Access<ComponentId>,
|
||||
last_run: Tick,
|
||||
this_run: Tick,
|
||||
) -> Self {
|
||||
|
@ -385,27 +392,20 @@ impl<'w> FilteredResourcesMut<'w> {
|
|||
}
|
||||
|
||||
/// Gets read-only access to all of the resources this `FilteredResourcesMut` can access.
|
||||
pub fn as_readonly(&self) -> FilteredResources<'_> {
|
||||
pub fn as_readonly(&self) -> FilteredResources<'_, 's> {
|
||||
FilteredResources::from(self)
|
||||
}
|
||||
|
||||
/// Returns a new instance with a shorter lifetime.
|
||||
/// This is useful if you have `&mut FilteredResourcesMut`, but you need `FilteredResourcesMut`.
|
||||
pub fn reborrow(&mut self) -> FilteredResourcesMut<'_> {
|
||||
pub fn reborrow(&mut self) -> FilteredResourcesMut<'_, 's> {
|
||||
// SAFETY: We have exclusive access to this access for the duration of `'_`, so there cannot be anything else that conflicts.
|
||||
unsafe {
|
||||
Self::new(
|
||||
self.world,
|
||||
self.access.clone(),
|
||||
self.last_run,
|
||||
self.this_run,
|
||||
)
|
||||
}
|
||||
unsafe { Self::new(self.world, self.access, self.last_run, self.this_run) }
|
||||
}
|
||||
|
||||
/// Returns a reference to the underlying [`Access`].
|
||||
pub fn access(&self) -> &Access<ComponentId> {
|
||||
&self.access
|
||||
self.access
|
||||
}
|
||||
|
||||
/// Returns `true` if the `FilteredResources` has read access to the given resource.
|
||||
|
@ -492,10 +492,15 @@ impl<'w> FilteredResourcesMut<'w> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a mut World> for FilteredResourcesMut<'a> {
|
||||
fn from(value: &'a mut World) -> Self {
|
||||
let mut access = Access::new();
|
||||
access.write_all_resources();
|
||||
impl<'w> From<&'w mut World> for FilteredResourcesMut<'w, 'static> {
|
||||
fn from(value: &'w mut World) -> Self {
|
||||
static WRITE_ALL_RESOURCES: OnceLock<Access<ComponentId>> = OnceLock::new();
|
||||
let access = WRITE_ALL_RESOURCES.get_or_init(|| {
|
||||
let mut access = Access::new();
|
||||
access.write_all_resources();
|
||||
access
|
||||
});
|
||||
|
||||
let last_run = value.last_change_tick();
|
||||
let this_run = value.change_tick();
|
||||
// SAFETY: We have a mutable reference to the entire world, so nothing else can alias with mutable access to all resources.
|
||||
|
|
Loading…
Reference in a new issue