From 3c8c135b9f41acf6a170822c0cba21a402f881d6 Mon Sep 17 00:00:00 2001 From: HampusM Date: Thu, 4 Apr 2024 21:07:11 +0200 Subject: feat(ecs): allow components to be specified to be dropped last --- ecs/src/component.rs | 2 ++ ecs/src/lib.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/ecs/src/component.rs b/ecs/src/component.rs index 120ba30..c1f8168 100644 --- a/ecs/src/component.rs +++ b/ecs/src/component.rs @@ -16,6 +16,8 @@ use crate::WorldData; pub trait Component: SystemInput + Any + TypeName { + fn drop_last(&self) -> bool; + #[doc(hidden)] fn as_any_mut(&mut self) -> &mut dyn Any; diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index 7a56f37..4d6e4e5 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -4,6 +4,7 @@ use std::any::{type_name, Any, TypeId}; use std::collections::{HashMap, HashSet}; use std::fmt::Debug; use std::marker::PhantomData; +use std::mem::ManuallyDrop; use std::ops::RangeBounds; use std::slice::Iter as SliceIter; use std::sync::{Arc, Weak}; @@ -35,7 +36,7 @@ pub use ecs_macros::Component; #[derive(Debug, Default)] struct Entity { - components: Vec, + components: Vec>, } #[derive(Debug)] @@ -43,6 +44,7 @@ struct EntityComponent { id: TypeId, component: Lock>, + drop_last: bool, } #[derive(Debug, Default)] @@ -73,9 +75,14 @@ impl World components: components .into_vec() .into_iter() - .map(|component| EntityComponent { - id: (*component).type_id(), - component: Lock::new(component), + .map(|component| { + let drop_last = component.drop_last(); + + ManuallyDrop::new(EntityComponent { + id: (*component).type_id(), + component: Lock::new(component), + drop_last, + }) }) .collect(), }); @@ -144,9 +151,14 @@ impl World .push(Entity { components: components .into_iter() - .map(|component| EntityComponent { - id: (*component).type_id(), - component: Lock::new(component), + .map(|component| { + let drop_last = component.drop_last(); + + ManuallyDrop::new(EntityComponent { + id: (*component).type_id(), + component: Lock::new(component), + drop_last, + }) }) .collect(), }); @@ -443,3 +455,48 @@ impl TypeName for ComponentStorage type_name::() } } + +impl Drop for ComponentStorage +{ + fn drop(&mut self) + { + let mut components_to_drop_last = Vec::new(); + + for entity in &mut self.entities { + for component in &mut entity.components { + if component.drop_last { + #[cfg(feature = "debug")] + tracing::debug!( + "Component {} pushed to dropping last queue", + component.component.read_nonblock().unwrap().type_name() + ); + + components_to_drop_last.push(component); + continue; + } + + #[cfg(feature = "debug")] + tracing::debug!( + "Dropping component {}", + component.component.read_nonblock().unwrap().type_name() + ); + + unsafe { + ManuallyDrop::drop(component); + } + } + } + + for component in &mut components_to_drop_last { + #[cfg(feature = "debug")] + tracing::debug!( + "Dropping component {} last", + component.component.read_nonblock().unwrap().type_name() + ); + + unsafe { + ManuallyDrop::drop(component); + } + } + } +} -- cgit v1.2.3-18-g5258