diff options
author | HampusM <hampus@hampusmat.com> | 2024-04-06 16:30:58 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2024-04-06 16:30:58 +0200 |
commit | c0fbe4b3790c771836b1723a81a2290d9796f429 (patch) | |
tree | 342a6f965b48e7473b467f23aff5e768b864b0cf /ecs/src/actions.rs | |
parent | 6038a5b701ee9ea3bd3b5da50d7d06930cd9a270 (diff) |
feat(ecs): add weak reference actions
Diffstat (limited to 'ecs/src/actions.rs')
-rw-r--r-- | ecs/src/actions.rs | 90 |
1 files changed, 70 insertions, 20 deletions
diff --git a/ecs/src/actions.rs b/ecs/src/actions.rs index a5aaf0c..cc27f09 100644 --- a/ecs/src/actions.rs +++ b/ecs/src/actions.rs @@ -1,44 +1,55 @@ use std::any::Any; +use std::marker::PhantomData; +use std::sync::{Arc, Weak}; use crate::component::{Component, Sequence as ComponentSequence}; +use crate::lock::{Lock, WriteGuard}; use crate::system::{NoInitParamFlag, Param as SystemParam, System}; use crate::tuple::FilterExclude as TupleFilterExclude; -use crate::WorldData; +use crate::{ActionQueue, WorldData}; /// Used to to queue up actions for a [`World`] to perform. #[derive(Debug)] pub struct Actions<'world> { - world_data: &'world WorldData, + action_queue: WriteGuard<'world, ActionQueue>, + action_queue_weak: Weak<Lock<ActionQueue>>, } impl<'world> Actions<'world> { /// Adds a spawning a new entity to the action queue. - /// - /// # Panics - /// Will panic if a mutable internal lock cannot be acquired. pub fn spawn<Comps: ComponentSequence>(&mut self, components: Comps) { - self.world_data - .action_queue - .write_nonblock() - .expect("Failed to aquire read-write action queue lock") - .push(Action::Spawn(components.into_vec())); + self.action_queue.push(Action::Spawn(components.into_vec())); } - /// Adds stopping the loop in [`Engine::event_loop`] at the next oppertune time to the + /// Adds stopping the loop in [`Engine::event_loop`] at the next opportune time to the /// action queue. - /// - /// # Panics - /// Will panic if a mutable internal lock cannot be acquired. pub fn stop(&mut self) { - self.world_data - .action_queue - .write_nonblock() - .expect("Failed to aquire read-write action queue lock") - .push(Action::Stop); + self.action_queue.push(Action::Stop); + } + + /// Returns a struct which holds a weak reference to the [`World`] that `Actions` + /// references and that can be used to aquire a new `Actions` instance if the + /// referenced [`World`] is still alive. + #[must_use] + pub fn to_weak_ref(&self) -> WeakRef + { + WeakRef { + action_queue: self.action_queue_weak.clone(), + } + } + + fn new(action_queue: &'world Arc<Lock<ActionQueue>>) -> Self + { + Self { + action_queue: action_queue + .write_nonblock() + .expect("Failed to aquire read-write action queue lock"), + action_queue_weak: Arc::downgrade(action_queue), + } } } @@ -59,7 +70,7 @@ unsafe impl<'world> SystemParam<'world> for Actions<'world> world_data: &'world WorldData, ) -> Self { - Self { world_data } + Self::new(&world_data.action_queue) } fn is_compatible<Other: SystemParam<'world>>() -> bool @@ -75,6 +86,45 @@ unsafe impl<'world> SystemParam<'world> for Actions<'world> } } +#[derive(Debug, Clone)] +pub struct WeakRef +{ + action_queue: Weak<Lock<ActionQueue>>, +} + +impl WeakRef +{ + /// Returns a struct which can be used to retrieve a [`Actions`]. + /// + /// Returns [`None`] if the referenced [`World`] has been dropped. + #[must_use] + pub fn access(&self) -> Option<Ref<'_>> + { + Some(Ref { + action_queue: self.action_queue.upgrade()?, + _pd: PhantomData, + }) + } +} + +/// Intermediate between [`Actions`] and [`WeakRef`]. Contains a strong reference to +/// a world which is not allowed direct access to. +#[derive(Debug, Clone)] +pub struct Ref<'weak_ref> +{ + action_queue: Arc<Lock<ActionQueue>>, + _pd: PhantomData<&'weak_ref ()>, +} + +impl<'weak_ref> Ref<'weak_ref> +{ + #[must_use] + pub fn to_actions(&self) -> Actions<'_> + { + Actions::new(&self.action_queue) + } +} + /// A action for a [`System`] to perform. #[derive(Debug)] pub(crate) enum Action |