From 80b4cc938dcd7b7db04072805ffc631559a4bbaa Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 28 Nov 2024 18:55:17 +0300 Subject: [PATCH] Fix constructors & destructors order Order of callbacks was affected by the order of caches, which are pretty much arbitrary. For a fix, explicitly order the callbacks globally per-world. --- libs/ecs/include/psemek/ecs/container.hpp | 15 +++++++++---- .../include/psemek/ecs/detail/callback.hpp | 16 ++++++++++++++ .../include/psemek/ecs/detail/query_cache.hpp | 2 +- libs/ecs/include/psemek/ecs/detail/table.hpp | 8 +++---- libs/ecs/source/detail/table.cpp | 22 ++++++++++--------- 5 files changed, 44 insertions(+), 19 deletions(-) diff --git a/libs/ecs/include/psemek/ecs/container.hpp b/libs/ecs/include/psemek/ecs/container.hpp index 78c9a4b4..98028110 100644 --- a/libs/ecs/include/psemek/ecs/container.hpp +++ b/libs/ecs/include/psemek/ecs/container.hpp @@ -403,6 +403,9 @@ namespace psemek::ecs detail::component_registry component_registry_; detail::index_container index_container_; + int next_constructor_id_ = 0; + int next_destructor_id_ = 0; + util::object_pool> uuid_list_pool_; util::object_pool> uuid_set_pool_; @@ -655,6 +658,8 @@ namespace psemek::ecs static_assert(invocable_type::value, "function is not invocable with these components"); + auto id = next_constructor_id_++; + auto constructor_factory = [function = std::move(function)](std::vector const & column_indices) -> detail::table_callback { return [function, column_indices](container & container, detail::table & table, std::uint32_t row, util::hash_set const & attached_components, bool force){ @@ -674,9 +679,9 @@ namespace psemek::ecs query_cache cache = this->cache(); - cache->constructor_factories.push_back(constructor_factory); + cache->constructor_factories.push_back([id, constructor_factory](auto const & ... args){ return detail::ordered_table_callback{id, constructor_factory(args...)}; }); for (auto const & entry : cache->entries) - entry.table->add_constructor(constructor_factory(entry.columns_indices)); + entry.table->add_constructor({id, constructor_factory(entry.columns_indices)}); } template @@ -688,6 +693,8 @@ namespace psemek::ecs static_assert(invocable_type::value, "function is not invocable with these components"); + auto id = next_destructor_id_++; + auto destructor_factory = [function = std::move(function)](std::vector const & column_indices) -> detail::table_callback { return [function, column_indices](container & container, detail::table & table, std::uint32_t row, util::hash_set const & detached_components, bool force){ @@ -707,9 +714,9 @@ namespace psemek::ecs query_cache cache = this->cache(); - cache->destructor_factories.push_back(destructor_factory); + cache->destructor_factories.push_back([id, destructor_factory](auto const & ... args){ return detail::ordered_table_callback{id, destructor_factory(args...)}; }); for (auto const & entry : cache->entries) - entry.table->add_destructor(destructor_factory(entry.columns_indices)); + entry.table->add_destructor({id, destructor_factory(entry.columns_indices)}); } template diff --git a/libs/ecs/include/psemek/ecs/detail/callback.hpp b/libs/ecs/include/psemek/ecs/detail/callback.hpp index be210916..02fa9e61 100644 --- a/libs/ecs/include/psemek/ecs/detail/callback.hpp +++ b/libs/ecs/include/psemek/ecs/detail/callback.hpp @@ -18,6 +18,22 @@ namespace psemek::ecs using table_callback = util::function const &, bool)>; + struct ordered_table_callback + { + int id; + table_callback callback; + + friend auto operator <=> (ordered_table_callback const & c1, ordered_table_callback const & c2) + { + return c1.id <=> c2.id; + } + + friend bool operator == (ordered_table_callback const & c1, ordered_table_callback const & c2) + { + return c1.id == c2.id; + } + }; + } } diff --git a/libs/ecs/include/psemek/ecs/detail/query_cache.hpp b/libs/ecs/include/psemek/ecs/detail/query_cache.hpp index 3aab1fe1..ff67391a 100644 --- a/libs/ecs/include/psemek/ecs/detail/query_cache.hpp +++ b/libs/ecs/include/psemek/ecs/detail/query_cache.hpp @@ -27,7 +27,7 @@ namespace psemek::ecs::detail std::list entries; - using callback_factory = util::function const &)>; + using callback_factory = util::function const &)>; std::vector constructor_factories; std::vector destructor_factories; diff --git a/libs/ecs/include/psemek/ecs/detail/table.hpp b/libs/ecs/include/psemek/ecs/detail/table.hpp index 181b101f..29f2aee7 100644 --- a/libs/ecs/include/psemek/ecs/detail/table.hpp +++ b/libs/ecs/include/psemek/ecs/detail/table.hpp @@ -70,8 +70,8 @@ namespace psemek::ecs::detail std::vector const & non_copyable_components() const; - void add_constructor(table_callback callback); - void add_destructor(table_callback callback); + void add_constructor(ordered_table_callback callback); + void add_destructor(ordered_table_callback callback); void trigger_constructors(container & container, std::uint32_t row); void trigger_constructors(container & container, std::uint32_t row, util::hash_set const & attached_components); @@ -97,8 +97,8 @@ namespace psemek::ecs::detail std::vector non_copyable_components_; - std::shared_ptr> constructors_; - std::shared_ptr> destructors_; + std::shared_ptr> constructors_; + std::shared_ptr> destructors_; }; } diff --git a/libs/ecs/source/detail/table.cpp b/libs/ecs/source/detail/table.cpp index 2011e881..90b2fb37 100644 --- a/libs/ecs/source/detail/table.cpp +++ b/libs/ecs/source/detail/table.cpp @@ -21,8 +21,8 @@ namespace psemek::ecs::detail columns_ = std::move(columns); - constructors_ = std::make_shared>(); - destructors_ = std::make_shared>(); + constructors_ = std::make_shared>(); + destructors_ = std::make_shared>(); } std::optional table::column_index(util::uuid const & uuid) const @@ -144,38 +144,40 @@ namespace psemek::ecs::detail return non_copyable_components_; } - void table::add_constructor(table_callback callback) + void table::add_constructor(ordered_table_callback callback) { - constructors_->push_back(std::move(callback)); + auto it = std::upper_bound(constructors_->begin(), constructors_->end(), callback); + constructors_->insert(it, std::move(callback)); } - void table::add_destructor(table_callback callback) + void table::add_destructor(ordered_table_callback callback) { - destructors_->push_back(std::move(callback)); + auto it = std::upper_bound(destructors_->begin(), destructors_->end(), callback); + destructors_->insert(it, std::move(callback)); } void table::trigger_constructors(container & container, std::uint32_t row) { for (auto const & callback : *constructors_) - callback(container, *this, row, column_uuid_set_, true); + callback.callback(container, *this, row, column_uuid_set_, true); } void table::trigger_constructors(container & container, std::uint32_t row, util::hash_set const & attached_components) { for (auto const & callback : *constructors_) - callback(container, *this, row, attached_components, false); + callback.callback(container, *this, row, attached_components, false); } void table::trigger_destructors(container & container, std::uint32_t row) { for (auto const & callback : *destructors_) - callback(container, *this, row, column_uuid_set_, true); + callback.callback(container, *this, row, column_uuid_set_, true); } void table::trigger_destructors(container & container, std::uint32_t row, util::hash_set const & detached_components) { for (auto const & callback : *destructors_) - callback(container, *this, row, detached_components, false); + callback.callback(container, *this, row, detached_components, false); } std::size_t table::memory_usage() const