From 4a4f680d0adc369f82c415e5edb463dc50c19ab2 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Fri, 10 Oct 2025 15:51:45 +0300 Subject: [PATCH] Add debug assertions for when an entity's archetype is changed while it is being created/destroyed --- libs/ecs/include/psemek/ecs/container.hpp | 29 +++++++++++++++++++++++ libs/ecs/source/container.cpp | 10 ++++++++ 2 files changed, 39 insertions(+) diff --git a/libs/ecs/include/psemek/ecs/container.hpp b/libs/ecs/include/psemek/ecs/container.hpp index 1a8b24fa..c112bb1d 100644 --- a/libs/ecs/include/psemek/ecs/container.hpp +++ b/libs/ecs/include/psemek/ecs/container.hpp @@ -394,6 +394,10 @@ namespace psemek::ecs std::size_t method_recursion_depth_ = 0; std::vector> finally_callbacks_; + #ifdef PSEMEK_DEBUG + util::hash_set currently_changing_archetype_; + #endif + detail::table * insert_table(std::vector> columns); void do_destroy(handle entity); void remove_row(detail::table & table, std::uint32_t row, util::span entities); @@ -434,6 +438,9 @@ namespace psemek::ecs auto row = table->row_count(); auto id = entity_list_.create(table, row); handle handle{id, entity_list_.get_entities()[id].epoch}; + #ifdef PSEMEK_DEBUG + currently_changing_archetype_.insert(handle); + #endif [[maybe_unused]] accessor accessor = get(handle); table->push_row(handle); @@ -441,6 +448,10 @@ namespace psemek::ecs table->trigger_constructors(*this, row); + #ifdef PSEMEK_DEBUG + currently_changing_archetype_.erase(handle); + #endif + finalize_method(); --method_recursion_depth_; @@ -453,6 +464,11 @@ namespace psemek::ecs { static_assert(detail::all_different_types_v...>, "all component types must be different"); + #ifdef PSEMEK_DEBUG + assert(!currently_changing_archetype_.contains(entity)); + currently_changing_archetype_.insert(entity); + #endif + ++method_recursion_depth_; (register_component(), ...); @@ -510,6 +526,10 @@ namespace psemek::ecs uuid_set_pool_.put(std::move(attached_uuid_set)); uuid_list_pool_.put(std::move(uuids)); + #ifdef PSEMEK_DEBUG + currently_changing_archetype_.erase(entity); + #endif + finalize_method(); --method_recursion_depth_; @@ -520,6 +540,11 @@ namespace psemek::ecs { static_assert(detail::all_different_types_v...>, "all component types must be different"); + #ifdef PSEMEK_DEBUG + assert(!currently_changing_archetype_.contains(entity)); + currently_changing_archetype_.insert(entity); + #endif + ++method_recursion_depth_; auto detached_uuid_set = uuid_set_pool_.get(); @@ -577,6 +602,10 @@ namespace psemek::ecs uuid_list_pool_.put(std::move(uuids)); uuid_set_pool_.put(std::move(detached_uuid_set)); + #ifdef PSEMEK_DEBUG + currently_changing_archetype_.erase(entity); + #endif + finalize_method(); --method_recursion_depth_; diff --git a/libs/ecs/source/container.cpp b/libs/ecs/source/container.cpp index 788ab5f3..b913960e 100644 --- a/libs/ecs/source/container.cpp +++ b/libs/ecs/source/container.cpp @@ -13,6 +13,11 @@ namespace psemek::ecs void container::destroy(handle entity) { + #ifdef PSEMEK_DEBUG + assert(!currently_changing_archetype_.contains(entity)); + currently_changing_archetype_.insert(entity); + #endif + assert(alive(entity)); ++method_recursion_depth_; @@ -23,10 +28,15 @@ namespace psemek::ecs do_destroy(entity); entity_list_.destroy(entity.id); + #ifdef PSEMEK_DEBUG + currently_changing_archetype_.erase(entity); + #endif + finalize_method(); --method_recursion_depth_; } + } accessor container::get(handle entity) {