From d435d9b80c46f995d56d385bc8a0de29e6d865cb Mon Sep 17 00:00:00 2001 From: HampusM Date: Thu, 11 Apr 2024 19:02:39 +0200 Subject: feat(ecs): add specifying to drop soles last --- ecs/src/lib.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- ecs/src/sole.rs | 2 ++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index 8a5de64..285f3b3 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -350,17 +350,26 @@ impl Drop for ComponentStorage #[error("Sole {0} already exists")] pub struct SoleAlreadyExistsError(pub &'static str); +#[derive(Debug)] +struct StoredSole +{ + sole: Arc>>, + drop_last: bool, +} + #[derive(Debug, Default)] struct SoleStorage { - storage: HashMap>>>, + storage: HashMap>, } impl SoleStorage { fn get(&self) -> Option<&Arc>>> { - self.storage.get(&TypeId::of::()) + self.storage + .get(&TypeId::of::()) + .map(|sole| &sole.sole) } fn insert(&mut self, sole: SoleT) -> Result<(), SoleAlreadyExistsError> @@ -371,11 +380,61 @@ impl SoleStorage return Err(SoleAlreadyExistsError(type_name::())); } + let drop_last = sole.drop_last(); + // TODO: Reconsider this maybe? #[allow(clippy::arc_with_non_send_sync)] - self.storage - .insert(sole_type_id, Arc::new(Lock::new(Box::new(sole)))); + self.storage.insert( + sole_type_id, + ManuallyDrop::new(StoredSole { + sole: Arc::new(Lock::new(Box::new(sole))), + drop_last, + }), + ); Ok(()) } } + +impl Drop for SoleStorage +{ + fn drop(&mut self) + { + let mut soles_to_drop_last = Vec::new(); + + for sole in self.storage.values_mut() { + if sole.drop_last { + #[cfg(feature = "debug")] + tracing::debug!( + "Sole {} pushed to dropping last queue", + sole.sole.read_nonblock().unwrap().type_name() + ); + + soles_to_drop_last.push(sole); + continue; + } + + #[cfg(feature = "debug")] + tracing::debug!( + "Dropping sole {}", + sole.sole.read_nonblock().unwrap().type_name() + ); + + unsafe { + ManuallyDrop::drop(sole); + } + } + + for sole in &mut soles_to_drop_last { + #[cfg(feature = "debug")] + tracing::debug!( + "Dropping sole {} last", + sole.sole.read_nonblock().unwrap().type_name() + ); + + unsafe { + ManuallyDrop::drop(sole); + } + } + } +} diff --git a/ecs/src/sole.rs b/ecs/src/sole.rs index 014ab7d..fcff8de 100644 --- a/ecs/src/sole.rs +++ b/ecs/src/sole.rs @@ -13,6 +13,8 @@ use crate::WorldData; /// A type which has a single instance and is shared globally. pub trait Sole: Any + TypeName { + fn drop_last(&self) -> bool; + fn as_any_mut(&mut self) -> &mut dyn Any; fn as_any(&self) -> &dyn Any; -- cgit v1.2.3-18-g5258