From 89c0abfadabd2be09650ec274a0c20dfe5fb185f Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Sat, 14 Aug 2021 22:26:41 +0200 Subject: [PATCH] entity: * reviewed entt_traits::combine * added entt_traits::reserved * use entt_traits::combine where it makes sense to slightly improve perf --- src/entt/entity/entity.hpp | 18 +++++++++++------- src/entt/entity/registry.hpp | 10 +++++----- src/entt/entity/sparse_set.hpp | 14 +++++++------- test/entt/entity/entity.cpp | 5 ++--- test/entt/entity/registry.cpp | 2 +- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/entt/entity/entity.hpp b/src/entt/entity/entity.hpp index 2559e59b2..143323438 100644 --- a/src/entt/entity/entity.hpp +++ b/src/entt/entity/entity.hpp @@ -86,6 +86,8 @@ public: using version_type = typename entity_traits::version_type; /*! @brief Difference type. */ using difference_type = typename entity_traits::difference_type; + /*! @brief Reserved identifier. */ + static constexpr entity_type reserved = entity_traits::entity_mask | (entity_traits::version_mask << entity_traits::entity_shift); /** * @brief Converts an entity to its underlying type. @@ -125,7 +127,7 @@ public: * @param version The version part of the identifier. * @return A properly constructed identifier. */ - [[nodiscard]] static constexpr value_type construct(const entity_type entity = entity_traits::entity_mask, const version_type version = entity_traits::version_mask) ENTT_NOEXCEPT { + [[nodiscard]] static constexpr value_type construct(const entity_type entity, const version_type version) ENTT_NOEXCEPT { return value_type{(entity & entity_traits::entity_mask) | (static_cast(version) << entity_traits::entity_shift)}; } @@ -139,9 +141,9 @@ public: * @param rhs The identifier from which to take the version part. * @return A properly constructed identifier. */ - [[nodiscard]] static constexpr value_type combine(const value_type lhs, const value_type rhs) ENTT_NOEXCEPT { + [[nodiscard]] static constexpr value_type combine(const entity_type lhs, const entity_type rhs) ENTT_NOEXCEPT { constexpr auto version_mask = (entity_traits::version_mask << entity_traits::entity_shift); - return value_type{to_entity(lhs) | (to_integral(rhs) & version_mask)}; + return value_type{(lhs & entity_traits::entity_mask) | (rhs & version_mask)}; } }; @@ -167,7 +169,8 @@ struct null_t { */ template [[nodiscard]] constexpr operator Entity() const ENTT_NOEXCEPT { - return entt_traits::construct(); + using entity_traits = entt_traits; + return entity_traits::combine(entity_traits::reserved, entity_traits::reserved); } /** @@ -220,7 +223,7 @@ struct null_t { template [[nodiscard]] constexpr Entity operator|(const Entity entity) const ENTT_NOEXCEPT { using entity_traits = entt_traits; - return entity_traits::construct(entity_traits::to_entity(*this), entity_traits::to_version(entity)); + return entity_traits::combine(entity_traits::reserved, entity_traits::to_integral(entity)); } }; @@ -260,7 +263,8 @@ struct tombstone_t { */ template [[nodiscard]] constexpr operator Entity() const ENTT_NOEXCEPT { - return entt_traits::construct(); + using entity_traits = entt_traits; + return entity_traits::combine(entity_traits::reserved, entity_traits::reserved); } /** @@ -313,7 +317,7 @@ struct tombstone_t { template [[nodiscard]] constexpr Entity operator|(const Entity entity) const ENTT_NOEXCEPT { using entity_traits = entt_traits; - return entity_traits::construct(entity_traits::to_entity(entity)); + return entity_traits::combine(entity_traits::to_integral(entity), entity_traits::reserved); } }; diff --git a/src/entt/entity/registry.hpp b/src/entt/entity/registry.hpp index 5fd637e72..f8b064283 100644 --- a/src/entt/entity/registry.hpp +++ b/src/entt/entity/registry.hpp @@ -130,19 +130,19 @@ class basic_registry { auto generate_identifier(const std::size_t pos) ENTT_NOEXCEPT { ENTT_ASSERT(pos < entity_traits::to_integral(null), "No entities available"); - return entity_traits::construct(static_cast(pos), {}); + return entity_traits::combine(static_cast(pos), {}); } auto recycle_identifier() ENTT_NOEXCEPT { ENTT_ASSERT(free_list != null, "No entities available"); const auto curr = entity_traits::to_entity(free_list); free_list = (tombstone | entities[curr]); - return (entities[curr] = entity_traits::construct(curr, entity_traits::to_version(entities[curr]))); + return (entities[curr] = entity_traits::combine(curr, entity_traits::to_integral(entities[curr]))); } auto release_entity(const Entity entity, const typename entity_traits::version_type version) { const typename entity_traits::version_type vers = version + (version == entity_traits::to_version(tombstone)); - entities[entity_traits::to_entity(entity)] = entity_traits::construct(entity_traits::to_entity(free_list), vers); + entities[entity_traits::to_entity(entity)] = entity_traits::construct(entity_traits::to_integral(free_list), vers); free_list = (tombstone | entity); return vers; } @@ -163,7 +163,7 @@ public: * @return The entity identifier without the version. */ [[nodiscard]] static entity_type entity(const entity_type entity) ENTT_NOEXCEPT { - return entity_traits::construct(entity_traits::to_entity(entity), {}); + return entity_traits::combine(entity_traits::to_integral(entity), {}); } /** @@ -414,7 +414,7 @@ public: } else { auto *it = &free_list; for(; entity_traits::to_entity(*it) != req; it = &entities[entity_traits::to_entity(*it)]); - *it = entity_traits::construct(curr, entity_traits::to_version(*it)); + *it = entity_traits::combine(curr, entity_traits::to_integral(*it)); return (entities[req] = hint); } } diff --git a/src/entt/entity/sparse_set.hpp b/src/entt/entity/sparse_set.hpp index c69464101..0689866ed 100644 --- a/src/entt/entity/sparse_set.hpp +++ b/src/entt/entity/sparse_set.hpp @@ -277,7 +277,7 @@ protected: const auto pos = static_cast(entity_traits::to_entity(ref)); ENTT_ASSERT(packed[pos] == entt, "Invalid entity identifier"); - packed[pos] = std::exchange(free_list, entity_traits::construct(static_cast(pos))); + packed[pos] = std::exchange(free_list, entity_traits::combine(static_cast(pos), entity_traits::reserved)); // lazy self-assignment guard ref = null; } @@ -589,7 +589,7 @@ public: resize_packed(sz + !(sz > len)); } - assure_page(page(entt))[offset(entt)] = entity_traits::construct(static_cast(count)); + assure_page(page(entt))[offset(entt)] = entity_traits::combine(static_cast(count), {}); packed[count] = entt; return count++; } @@ -610,7 +610,7 @@ public: } else { ENTT_ASSERT(!contains(entt), "Set already contains entity"); const auto pos = static_cast(entity_traits::to_entity(free_list)); - assure_page(page(entt))[offset(entt)] = entity_traits::construct(static_cast(pos)); + assure_page(page(entt))[offset(entt)] = entity_traits::combine(static_cast(pos), {}); free_list = std::exchange(packed[pos], entt); return pos; } @@ -634,7 +634,7 @@ public: for(; first != last; ++first) { const auto entt = *first; ENTT_ASSERT(!contains(entt), "Set already contains entity"); - assure_page(page(entt))[offset(entt)] = entity_traits::construct(static_cast(count)); + assure_page(page(entt))[offset(entt)] = entity_traits::combine(static_cast(count), {}); packed[count++] = entt; } } @@ -710,8 +710,8 @@ public: --next; move_and_pop(next, pos); std::swap(packed[next], packed[pos]); - sparse[page(packed[pos])][offset(packed[pos])] = entity_traits::construct(static_cast(pos)); - *it = entity_traits::construct(static_cast(next)); + sparse[page(packed[pos])][offset(packed[pos])] = entity_traits::combine(static_cast(pos), {}); + *it = entity_traits::combine(static_cast(next), entity_traits::reserved); for(; next && packed[next - 1u] == tombstone; --next); } } @@ -796,7 +796,7 @@ public: const auto entt = packed[curr]; swap_at(next, idx); - sparse[page(entt)][offset(entt)] = entity_traits::construct(static_cast(curr)); + sparse[page(entt)][offset(entt)] = entity_traits::combine(static_cast(curr), {}); curr = std::exchange(next, idx); } } diff --git a/test/entt/entity/entity.cpp b/test/entt/entity/entity.cpp index 0c1938c00..bf31a8333 100644 --- a/test/entt/entity/entity.cpp +++ b/test/entt/entity/entity.cpp @@ -23,13 +23,12 @@ TEST(Entity, Traits) { ASSERT_EQ(traits_type::construct(traits_type::to_entity(entity), traits_type::to_version(entity)), entity); ASSERT_EQ(traits_type::construct(traits_type::to_entity(other), traits_type::to_version(other)), other); - ASSERT_EQ(traits_type::construct(traits_type::to_entity(other), traits_type::to_version(entity)), traits_type::combine(other, entity)); ASSERT_NE(traits_type::construct(traits_type::to_entity(entity), {}), entity); + ASSERT_EQ(traits_type::construct(traits_type::to_entity(other), traits_type::to_version(entity)), traits_type::combine(traits_type::to_integral(other), traits_type::to_integral(entity))); + ASSERT_EQ(traits_type::combine(entt::tombstone, entt::null), entt::tombstone | static_cast(entt::null)); ASSERT_EQ(traits_type::combine(entt::null, entt::tombstone), entt::null | static_cast(entt::tombstone)); - - ASSERT_EQ(traits_type::construct(), entt::entity{~entt::id_type{}}); } TEST(Entity, Null) { diff --git a/test/entt/entity/registry.cpp b/test/entt/entity/registry.cpp index 75c3dd073..c9257c5e0 100644 --- a/test/entt/entity/registry.cpp +++ b/test/entt/entity/registry.cpp @@ -685,7 +685,7 @@ TEST(Registry, VersionOverflow) { ASSERT_NE(registry.current(entity), registry.version(entity)); ASSERT_NE(registry.current(entity), typename traits_type::version_type{}); - registry.release(registry.create(), traits_type::to_version(traits_type::construct()) - 1u); + registry.release(registry.create(), traits_type::to_version(entt::tombstone) - 1u); registry.release(registry.create()); ASSERT_EQ(registry.current(entity), registry.version(entity));