summaryrefslogtreecommitdiff
path: root/ecs/src/actions.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2024-04-06 16:30:58 +0200
committerHampusM <hampus@hampusmat.com>2024-04-06 16:30:58 +0200
commitc0fbe4b3790c771836b1723a81a2290d9796f429 (patch)
tree342a6f965b48e7473b467f23aff5e768b864b0cf /ecs/src/actions.rs
parent6038a5b701ee9ea3bd3b5da50d7d06930cd9a270 (diff)
feat(ecs): add weak reference actions
Diffstat (limited to 'ecs/src/actions.rs')
-rw-r--r--ecs/src/actions.rs90
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