diff --git a/TODO b/TODO index e78278c22..6ede70504 100644 --- a/TODO +++ b/TODO @@ -44,3 +44,4 @@ TODO: * dtor, traits and custom should be part of meta descriptor maybe (?) * allow attaching const values of non-Type type to meta types * built-in no-pagination storage - no_pagination page size as limits::max +* avoid specializations of sigh_type in basic_sigh_mixin due to alloc type diff --git a/src/entt/entity/mixin.hpp b/src/entt/entity/mixin.hpp index cf90ac2d4..5794b725f 100644 --- a/src/entt/entity/mixin.hpp +++ b/src/entt/entity/mixin.hpp @@ -390,7 +390,9 @@ class basic_reactive_mixin final: public Type { using underlying_type = Type; using owner_type = Registry; + using alloc_traits = std::allocator_traits; using basic_registry_type = basic_registry; + using container_type = std::vector>; static_assert(std::is_base_of_v, "Invalid registry type"); @@ -429,7 +431,8 @@ class basic_reactive_mixin final: public Type { */ explicit basic_reactive_mixin(const allocator_type &allocator) : underlying_type{allocator}, - owner{} { + owner{}, + conn{allocator} { } /*! @brief Default copy constructor, deleted on purpose. */ @@ -441,7 +444,9 @@ class basic_reactive_mixin final: public Type { */ basic_reactive_mixin(basic_reactive_mixin &&other) noexcept : underlying_type{std::move(other)}, - owner{other.owner} {} + owner{other.owner}, + conn{} { + } /** * @brief Allocator-extended move constructor. @@ -450,7 +455,9 @@ class basic_reactive_mixin final: public Type { */ basic_reactive_mixin(basic_reactive_mixin &&other, const allocator_type &allocator) : underlying_type{std::move(other), allocator}, - owner{other.owner} {} + owner{other.owner}, + conn{allocator} { + } /*! @brief Default destructor. */ ~basic_reactive_mixin() override = default; @@ -467,18 +474,8 @@ class basic_reactive_mixin final: public Type { * @return This mixin. */ basic_reactive_mixin &operator=(basic_reactive_mixin &&other) noexcept { - swap(other); - return *this; - } - - /** - * @brief Exchanges the contents with those of a given storage. - * @param other Storage to exchange the content with. - */ - void swap(basic_reactive_mixin &other) noexcept { - using std::swap; - swap(owner, other.owner); underlying_type::swap(other); + return *this; } /** @@ -490,7 +487,8 @@ class basic_reactive_mixin final: public Type { */ template basic_reactive_mixin &on_construct(const id_type id = type_hash::value()) { - owner_or_assert().template storage(id).on_construct().template connect(*this); + auto curr = owner_or_assert().template storage(id).on_construct().template connect(*this); + conn.push_back(std::move(curr)); return *this; } @@ -503,7 +501,8 @@ class basic_reactive_mixin final: public Type { */ template basic_reactive_mixin &on_update(const id_type id = type_hash::value()) { - owner_or_assert().template storage(id).on_update().template connect(*this); + auto curr = owner_or_assert().template storage(id).on_update().template connect(*this); + conn.push_back(std::move(curr)); return *this; } @@ -516,7 +515,8 @@ class basic_reactive_mixin final: public Type { */ template basic_reactive_mixin &on_destroy(const id_type id = type_hash::value()) { - owner_or_assert().template storage(id).on_destroy().template connect(*this); + auto curr = owner_or_assert().template storage(id).on_destroy().template connect(*this); + conn.push_back(std::move(curr)); return *this; } @@ -564,8 +564,17 @@ class basic_reactive_mixin final: public Type { return {*this, parent.template storage>()..., parent.template storage>()...}; } + void reset() { + for(auto &&curr: conn) { + curr.release(); + } + + conn.clear(); + } + private: basic_registry_type *owner; + container_type conn; }; } // namespace entt diff --git a/test/entt/entity/reactive_mixin.cpp b/test/entt/entity/reactive_mixin.cpp index ea2202c16..d9f215e6c 100644 --- a/test/entt/entity/reactive_mixin.cpp +++ b/test/entt/entity/reactive_mixin.cpp @@ -534,6 +534,40 @@ ENTT_DEBUG_TYPED_TEST(ReactiveMixinDeathTest, View) { ASSERT_DEATH([[maybe_unused]] const auto cview = std::as_const(pool).view(), ""); } +TYPED_TEST(ReactiveMixin, AutoDisconnection) { + using value_type = typename TestFixture::type; + + entt::registry registry; + entt::reactive_mixin> pool; + const std::array entity{registry.create(), registry.create(), registry.create()}; + + ASSERT_TRUE(pool.empty()); + + ASSERT_TRUE(registry.on_construct().empty()); + ASSERT_TRUE(registry.on_update().empty()); + ASSERT_TRUE(registry.on_destroy().empty()); + + pool.bind(registry); + pool.template on_construct(); + pool.template on_update(); + pool.template on_destroy(); + registry.emplace(entity[0u]); + + ASSERT_FALSE(pool.empty()); + + ASSERT_FALSE(registry.on_construct().empty()); + ASSERT_FALSE(registry.on_update().empty()); + ASSERT_FALSE(registry.on_destroy().empty()); + + pool.reset(); + + ASSERT_FALSE(pool.empty()); + + ASSERT_TRUE(registry.on_construct().empty()); + ASSERT_TRUE(registry.on_update().empty()); + ASSERT_TRUE(registry.on_destroy().empty()); +} + TYPED_TEST(ReactiveMixin, CustomAllocator) { using value_type = typename TestFixture::type; using storage_type = entt::reactive_mixin>>;