Browse Source

entity:
* reviewed entt_traits<T>::combine
* added entt_traits::reserved
* use entt_traits<T>::combine where it makes sense to slightly improve perf

Michele Caini 4 years ago
parent
commit
89c0abfada

+ 11 - 7
src/entt/entity/entity.hpp

@@ -86,6 +86,8 @@ public:
     using version_type = typename entity_traits::version_type;
     using version_type = typename entity_traits::version_type;
     /*! @brief Difference type. */
     /*! @brief Difference type. */
     using difference_type = typename entity_traits::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.
      * @brief Converts an entity to its underlying type.
@@ -125,7 +127,7 @@ public:
      * @param version The version part of the identifier.
      * @param version The version part of the identifier.
      * @return A properly constructed 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<entity_type>(version) << entity_traits::entity_shift)};
         return value_type{(entity & entity_traits::entity_mask) | (static_cast<entity_type>(version) << entity_traits::entity_shift)};
     }
     }
 
 
@@ -139,9 +141,9 @@ public:
      * @param rhs The identifier from which to take the version part.
      * @param rhs The identifier from which to take the version part.
      * @return A properly constructed identifier.
      * @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);
         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<typename Entity>
     template<typename Entity>
     [[nodiscard]] constexpr operator Entity() const ENTT_NOEXCEPT {
     [[nodiscard]] constexpr operator Entity() const ENTT_NOEXCEPT {
-        return entt_traits<Entity>::construct();
+        using entity_traits = entt_traits<Entity>;
+        return entity_traits::combine(entity_traits::reserved, entity_traits::reserved);
     }
     }
 
 
     /**
     /**
@@ -220,7 +223,7 @@ struct null_t {
     template<typename Entity>
     template<typename Entity>
     [[nodiscard]] constexpr Entity operator|(const Entity entity) const ENTT_NOEXCEPT {
     [[nodiscard]] constexpr Entity operator|(const Entity entity) const ENTT_NOEXCEPT {
         using entity_traits = entt_traits<Entity>;
         using entity_traits = entt_traits<Entity>;
-        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<typename Entity>
     template<typename Entity>
     [[nodiscard]] constexpr operator Entity() const ENTT_NOEXCEPT {
     [[nodiscard]] constexpr operator Entity() const ENTT_NOEXCEPT {
-        return entt_traits<Entity>::construct();
+        using entity_traits = entt_traits<Entity>;
+        return entity_traits::combine(entity_traits::reserved, entity_traits::reserved);
     }
     }
 
 
     /**
     /**
@@ -313,7 +317,7 @@ struct tombstone_t {
     template<typename Entity>
     template<typename Entity>
     [[nodiscard]] constexpr Entity operator|(const Entity entity) const ENTT_NOEXCEPT {
     [[nodiscard]] constexpr Entity operator|(const Entity entity) const ENTT_NOEXCEPT {
         using entity_traits = entt_traits<Entity>;
         using entity_traits = entt_traits<Entity>;
-        return entity_traits::construct(entity_traits::to_entity(entity));
+        return entity_traits::combine(entity_traits::to_integral(entity), entity_traits::reserved);
     }
     }
 };
 };
 
 

+ 5 - 5
src/entt/entity/registry.hpp

@@ -130,19 +130,19 @@ class basic_registry {
 
 
     auto generate_identifier(const std::size_t pos) ENTT_NOEXCEPT {
     auto generate_identifier(const std::size_t pos) ENTT_NOEXCEPT {
         ENTT_ASSERT(pos < entity_traits::to_integral(null), "No entities available");
         ENTT_ASSERT(pos < entity_traits::to_integral(null), "No entities available");
-        return entity_traits::construct(static_cast<typename entity_traits::entity_type>(pos), {});
+        return entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), {});
     }
     }
 
 
     auto recycle_identifier() ENTT_NOEXCEPT {
     auto recycle_identifier() ENTT_NOEXCEPT {
         ENTT_ASSERT(free_list != null, "No entities available");
         ENTT_ASSERT(free_list != null, "No entities available");
         const auto curr = entity_traits::to_entity(free_list);
         const auto curr = entity_traits::to_entity(free_list);
         free_list = (tombstone | entities[curr]);
         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) {
     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));
         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);
         free_list = (tombstone | entity);
         return vers;
         return vers;
     }
     }
@@ -163,7 +163,7 @@ public:
      * @return The entity identifier without the version.
      * @return The entity identifier without the version.
      */
      */
     [[nodiscard]] static entity_type entity(const entity_type entity) ENTT_NOEXCEPT {
     [[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 {
         } else {
             auto *it = &free_list;
             auto *it = &free_list;
             for(; entity_traits::to_entity(*it) != req; it = &entities[entity_traits::to_entity(*it)]);
             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);
             return (entities[req] = hint);
         }
         }
     }
     }

+ 7 - 7
src/entt/entity/sparse_set.hpp

@@ -277,7 +277,7 @@ protected:
         const auto pos = static_cast<size_type>(entity_traits::to_entity(ref));
         const auto pos = static_cast<size_type>(entity_traits::to_entity(ref));
         ENTT_ASSERT(packed[pos] == entt, "Invalid entity identifier");
         ENTT_ASSERT(packed[pos] == entt, "Invalid entity identifier");
 
 
-        packed[pos] = std::exchange(free_list, entity_traits::construct(static_cast<typename entity_traits::entity_type>(pos)));
+        packed[pos] = std::exchange(free_list, entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), entity_traits::reserved));
         // lazy self-assignment guard
         // lazy self-assignment guard
         ref = null;
         ref = null;
     }
     }
@@ -589,7 +589,7 @@ public:
             resize_packed(sz + !(sz > len));
             resize_packed(sz + !(sz > len));
         }
         }
 
 
-        assure_page(page(entt))[offset(entt)] = entity_traits::construct(static_cast<typename entity_traits::entity_type>(count));
+        assure_page(page(entt))[offset(entt)] = entity_traits::combine(static_cast<typename entity_traits::entity_type>(count), {});
         packed[count] = entt;
         packed[count] = entt;
         return count++;
         return count++;
     }
     }
@@ -610,7 +610,7 @@ public:
         } else {
         } else {
             ENTT_ASSERT(!contains(entt), "Set already contains entity");
             ENTT_ASSERT(!contains(entt), "Set already contains entity");
             const auto pos = static_cast<size_type>(entity_traits::to_entity(free_list));
             const auto pos = static_cast<size_type>(entity_traits::to_entity(free_list));
-            assure_page(page(entt))[offset(entt)] = entity_traits::construct(static_cast<typename entity_traits::entity_type>(pos));
+            assure_page(page(entt))[offset(entt)] = entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), {});
             free_list = std::exchange(packed[pos], entt);
             free_list = std::exchange(packed[pos], entt);
             return pos;
             return pos;
         }
         }
@@ -634,7 +634,7 @@ public:
         for(; first != last; ++first) {
         for(; first != last; ++first) {
             const auto entt = *first;
             const auto entt = *first;
             ENTT_ASSERT(!contains(entt), "Set already contains entity");
             ENTT_ASSERT(!contains(entt), "Set already contains entity");
-            assure_page(page(entt))[offset(entt)] = entity_traits::construct(static_cast<typename entity_traits::entity_type>(count));
+            assure_page(page(entt))[offset(entt)] = entity_traits::combine(static_cast<typename entity_traits::entity_type>(count), {});
             packed[count++] = entt;
             packed[count++] = entt;
         }
         }
     }
     }
@@ -710,8 +710,8 @@ public:
                 --next;
                 --next;
                 move_and_pop(next, pos);
                 move_and_pop(next, pos);
                 std::swap(packed[next], packed[pos]);
                 std::swap(packed[next], packed[pos]);
-                sparse[page(packed[pos])][offset(packed[pos])] = entity_traits::construct(static_cast<const typename entity_traits::entity_type>(pos));
-                *it = entity_traits::construct(static_cast<typename entity_traits::entity_type>(next));
+                sparse[page(packed[pos])][offset(packed[pos])] = entity_traits::combine(static_cast<const typename entity_traits::entity_type>(pos), {});
+                *it = entity_traits::combine(static_cast<typename entity_traits::entity_type>(next), entity_traits::reserved);
                 for(; next && packed[next - 1u] == tombstone; --next);
                 for(; next && packed[next - 1u] == tombstone; --next);
             }
             }
         }
         }
@@ -796,7 +796,7 @@ public:
                 const auto entt = packed[curr];
                 const auto entt = packed[curr];
 
 
                 swap_at(next, idx);
                 swap_at(next, idx);
-                sparse[page(entt)][offset(entt)] = entity_traits::construct(static_cast<typename entity_traits::entity_type>(curr));
+                sparse[page(entt)][offset(entt)] = entity_traits::combine(static_cast<typename entity_traits::entity_type>(curr), {});
                 curr = std::exchange(next, idx);
                 curr = std::exchange(next, idx);
             }
             }
         }
         }

+ 2 - 3
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(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(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_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::entity>(entt::null));
     ASSERT_EQ(traits_type::combine(entt::tombstone, entt::null), entt::tombstone | static_cast<entt::entity>(entt::null));
     ASSERT_EQ(traits_type::combine(entt::null, entt::tombstone), entt::null | static_cast<entt::entity>(entt::tombstone));
     ASSERT_EQ(traits_type::combine(entt::null, entt::tombstone), entt::null | static_cast<entt::entity>(entt::tombstone));
-
-    ASSERT_EQ(traits_type::construct(), entt::entity{~entt::id_type{}});
 }
 }
 
 
 TEST(Entity, Null) {
 TEST(Entity, Null) {

+ 1 - 1
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), registry.version(entity));
     ASSERT_NE(registry.current(entity), typename traits_type::version_type{});
     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());
     registry.release(registry.create());
 
 
     ASSERT_EQ(registry.current(entity), registry.version(entity));
     ASSERT_EQ(registry.current(entity), registry.version(entity));