Cleanup deferred systems
This commit is contained in:
parent
3232fb392a
commit
8cf201d648
|
@ -1,7 +1,11 @@
|
||||||
use bevy::ecs::{
|
use bevy::{
|
||||||
system::{IntoSystem, Resource, SystemId},
|
ecs::{
|
||||||
world::World,
|
system::{IntoSystem, Resource, SystemId},
|
||||||
|
world::World,
|
||||||
|
},
|
||||||
|
utils::HashMap,
|
||||||
};
|
};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct DeferredSystem {
|
pub struct DeferredSystem {
|
||||||
|
@ -10,14 +14,23 @@ pub struct DeferredSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeferredSystem {
|
impl DeferredSystem {
|
||||||
pub(crate) fn new<S>(system: S, world: &mut World) -> Self
|
pub(crate) fn new<S>(system: S, world: &mut World) -> (Self, Arc<()>)
|
||||||
where
|
where
|
||||||
S: IntoSystem<(), (), ()> + 'static,
|
S: IntoSystem<(), (), ()> + 'static,
|
||||||
{
|
{
|
||||||
Self {
|
let id = world.register_system(system);
|
||||||
id: world.register_system(system), // TODO: We never unregister the system
|
let ref_count = Arc::new(());
|
||||||
run_queue: Box::as_mut(&mut world.resource_mut::<DeferredSystemRunQueue>().0),
|
|
||||||
}
|
let mut system_registry = world.resource_mut::<DeferredSystemRegistry>();
|
||||||
|
system_registry
|
||||||
|
.ref_counts
|
||||||
|
.insert(id, Arc::clone(&ref_count));
|
||||||
|
|
||||||
|
let deferred_system = Self {
|
||||||
|
id,
|
||||||
|
run_queue: Box::as_mut(&mut system_registry.run_queue),
|
||||||
|
};
|
||||||
|
(deferred_system, ref_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn schedule(&self) {
|
pub fn schedule(&self) {
|
||||||
|
@ -28,5 +41,8 @@ impl DeferredSystem {
|
||||||
unsafe impl Send for DeferredSystem {}
|
unsafe impl Send for DeferredSystem {}
|
||||||
unsafe impl Sync for DeferredSystem {}
|
unsafe impl Sync for DeferredSystem {}
|
||||||
|
|
||||||
#[derive(Resource, Clone, Default)]
|
#[derive(Resource, Default)]
|
||||||
pub struct DeferredSystemRunQueue(pub Box<Vec<SystemId>>);
|
pub struct DeferredSystemRegistry {
|
||||||
|
pub ref_counts: HashMap<SystemId, Arc<()>>,
|
||||||
|
pub run_queue: Box<Vec<SystemId>>,
|
||||||
|
}
|
||||||
|
|
|
@ -26,7 +26,8 @@ impl DioxusUiHooks for ScopeState {
|
||||||
where
|
where
|
||||||
S: IntoSystem<(), (), ()> + 'static,
|
S: IntoSystem<(), (), ()> + 'static,
|
||||||
{
|
{
|
||||||
*self.use_hook(|| DeferredSystem::new(system, EcsContext::get_world(self)))
|
self.use_hook(|| DeferredSystem::new(system, EcsContext::get_world(self)))
|
||||||
|
.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ mod tick;
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
bsn::Bsn,
|
bsn::Bsn,
|
||||||
deferred_system::DeferredSystemRunQueue,
|
deferred_system::DeferredSystemRegistry,
|
||||||
tick::{tick_dioxus_ui, VirtualDomUnsafe},
|
tick::{tick_dioxus_ui, VirtualDomUnsafe},
|
||||||
};
|
};
|
||||||
use bevy::{
|
use bevy::{
|
||||||
|
@ -23,7 +23,7 @@ pub struct DioxusUiPlugin;
|
||||||
|
|
||||||
impl Plugin for DioxusUiPlugin {
|
impl Plugin for DioxusUiPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.init_resource::<DeferredSystemRunQueue>()
|
app.init_resource::<DeferredSystemRegistry>()
|
||||||
.add_systems(Update, tick_dioxus_ui);
|
.add_systems(Update, tick_dioxus_ui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
23
src/tick.rs
23
src/tick.rs
|
@ -1,13 +1,16 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
apply_mutations::apply_mutations, deferred_system::DeferredSystemRunQueue, DioxusUiRoot,
|
apply_mutations::apply_mutations, deferred_system::DeferredSystemRegistry, DioxusUiRoot,
|
||||||
};
|
};
|
||||||
use bevy::{
|
use bevy::{
|
||||||
ecs::{entity::Entity, world::World},
|
ecs::{
|
||||||
|
entity::Entity,
|
||||||
|
world::{Mut, World},
|
||||||
|
},
|
||||||
prelude::{Deref, DerefMut},
|
prelude::{Deref, DerefMut},
|
||||||
utils::synccell::SyncCell,
|
utils::synccell::SyncCell,
|
||||||
};
|
};
|
||||||
use dioxus_core::{Element, Scope, ScopeState, VirtualDom};
|
use dioxus_core::{Element, Scope, ScopeState, VirtualDom};
|
||||||
use std::mem;
|
use std::{mem, sync::Arc};
|
||||||
|
|
||||||
// TODO: This is not sound. Can't borrow the world while iterating over DioxusUiRoots.
|
// TODO: This is not sound. Can't borrow the world while iterating over DioxusUiRoots.
|
||||||
pub fn tick_dioxus_ui(world: &mut World) {
|
pub fn tick_dioxus_ui(world: &mut World) {
|
||||||
|
@ -55,9 +58,19 @@ pub fn tick_dioxus_ui(world: &mut World) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for system_id in mem::take(&mut *world.resource_mut::<DeferredSystemRunQueue>().0) {
|
for system_id in mem::take(&mut *world.resource_mut::<DeferredSystemRegistry>().run_queue) {
|
||||||
world.run_system(system_id).unwrap();
|
let _ = world.run_system(system_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
world.resource_scope(|world, mut system_registry: Mut<DeferredSystemRegistry>| {
|
||||||
|
system_registry.ref_counts.retain(|system_id, ref_count| {
|
||||||
|
let cleanup = Arc::strong_count(ref_count) == 1;
|
||||||
|
if cleanup {
|
||||||
|
world.remove_system(*system_id).unwrap();
|
||||||
|
}
|
||||||
|
!cleanup
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
Loading…
Reference in a new issue