Просмотр исходного кода

sparse_set/storage: drop length in favor of a temporary function to make the transition easier

Michele Caini 2 лет назад
Родитель
Сommit
9732f0547d
2 измененных файлов с 38 добавлено и 54 удалено
  1. 8 0
      src/entt/entity/sparse_set.hpp
  2. 30 54
      src/entt/entity/storage.hpp

+ 8 - 0
src/entt/entity/sparse_set.hpp

@@ -252,6 +252,14 @@ protected:
     /*! @brief Random access iterator type. */
     using basic_iterator = internal::sparse_set_iterator<packed_container_type>;
 
+    /**
+     * @brief Temporary function to make the transition easier. Don't use me.
+     * @param len The length to use.
+     */
+    void swap_only_length_temporary_function(const std::size_t len) {
+        head = static_cast<underlying_type>(len);
+    }
+
     /**
      * @brief Erases an entity from a sparse set.
      * @param it An iterator to the element to pop.

+ 30 - 54
src/entt/entity/storage.hpp

@@ -967,7 +967,7 @@ class basic_storage<Entity, Entity, Allocator>
 
 private:
     void swap_or_move([[maybe_unused]] const std::size_t lhs, [[maybe_unused]] const std::size_t rhs) override {
-        ENTT_ASSERT(((lhs < length) + (rhs < length)) != 1u, "Cross swapping is not supported");
+        ENTT_ASSERT(((lhs < base_type::free_list()) + (rhs < base_type::free_list())) != 1u, "Cross swapping is not supported");
     }
 
 protected:
@@ -978,24 +978,18 @@ protected:
      */
     void pop(underlying_iterator first, underlying_iterator last) override {
         for(; first != last; ++first) {
-            if(const auto pos = base_type::index(*first); pos < length) {
+            if(const auto pos = base_type::index(*first); pos < base_type::free_list()) {
                 base_type::bump(local_traits_type::next(*first));
 
-                if(const size_type slot = length - 1u; pos != slot) {
+                if(const size_type slot = base_type::free_list() - 1u; pos != slot) {
                     base_type::swap_elements(base_type::data()[pos], base_type::data()[slot]);
                 }
 
-                --length;
+                base_type::swap_only_length_temporary_function(base_type::free_list() - 1u);
             }
         }
     }
 
-    /*! @brief Erases all entities of a sparse set. */
-    void pop_all() override {
-        length = 0u;
-        base_type::pop_all();
-    }
-
     /**
      * @brief Assigns an entity to a storage.
      * @param hint A valid identifier.
@@ -1037,16 +1031,14 @@ public:
      * @param allocator The allocator to use.
      */
     explicit basic_storage(const allocator_type &allocator)
-        : base_type{type_id<value_type>(), deletion_policy::swap_only, allocator},
-          length{} {}
+        : base_type{type_id<value_type>(), deletion_policy::swap_only, allocator} {}
 
     /**
      * @brief Move constructor.
      * @param other The instance to move from.
      */
     basic_storage(basic_storage &&other) noexcept
-        : base_type{std::move(other)},
-          length{std::exchange(other.length, size_type{})} {}
+        : base_type{std::move(other)} {}
 
     /**
      * @brief Allocator-extended move constructor.
@@ -1054,8 +1046,7 @@ public:
      * @param allocator The allocator to use.
      */
     basic_storage(basic_storage &&other, const allocator_type &allocator) noexcept
-        : base_type{std::move(other), allocator},
-          length{std::exchange(other.length, size_type{})} {}
+        : base_type{std::move(other), allocator} {}
 
     /**
      * @brief Move assignment operator.
@@ -1064,7 +1055,6 @@ public:
      */
     basic_storage &operator=(basic_storage &&other) noexcept {
         base_type::operator=(std::move(other));
-        length = std::exchange(other.length, size_type{});
         return *this;
     }
 
@@ -1078,7 +1068,7 @@ public:
      * @param entt A valid identifier.
      */
     void get([[maybe_unused]] const entity_type entt) const noexcept {
-        ENTT_ASSERT(base_type::index(entt) < length, "The requested entity is not a live one");
+        ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
     }
 
     /**
@@ -1092,30 +1082,18 @@ public:
      * @return Returns an empty tuple.
      */
     [[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const noexcept {
-        ENTT_ASSERT(base_type::index(entt) < length, "The requested entity is not a live one");
+        ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
         return std::tuple{};
     }
 
-    /**
-     * @brief Exchanges the contents with those of a given storage.
-     * @param other Storage to exchange the content with.
-     */
-    void swap(basic_storage &other) {
-        using std::swap;
-        base_type::swap(other);
-        swap(length, other.length);
-    }
-
     /**
      * @brief Creates a new identifier or recycles a destroyed one.
      * @return A valid identifier.
      */
     entity_type emplace() {
-        if(length == base_type::size()) {
-            return *base_type::try_emplace(entity_at(length++), true);
-        }
-
-        return base_type::operator[](length++);
+        const auto len = base_type::free_list();
+        base_type::swap_only_length_temporary_function(len + 1u);
+        return (len == base_type::size()) ? *base_type::try_emplace(entity_at(len), true) : base_type::operator[](len);
     }
 
     /**
@@ -1137,13 +1115,13 @@ public:
                 base_type::try_emplace(entity_at(base_type::size()), true);
             }
 
-            base_type::swap_elements(base_type::data()[pos], base_type::data()[length]);
-            ++length;
-        } else if(const auto idx = base_type::index(curr); idx < length) {
+            base_type::swap_elements(base_type::data()[pos], base_type::data()[base_type::free_list()]);
+            base_type::swap_only_length_temporary_function(base_type::free_list() + 1u);
+        } else if(const auto idx = base_type::index(curr); idx < base_type::free_list()) {
             return emplace();
         } else {
-            base_type::swap_elements(base_type::data()[idx], base_type::data()[length]);
-            ++length;
+            base_type::swap_elements(base_type::data()[idx], base_type::data()[base_type::free_list()]);
+            base_type::swap_only_length_temporary_function(base_type::free_list() + 1u);
         }
 
         base_type::bump(hint);
@@ -1171,12 +1149,13 @@ public:
      */
     template<typename It>      
     void insert(It first, It last) {
-        for(const auto sz = base_type::size(); first != last && length != sz; ++first, ++length) {
-            *first = base_type::operator[](length);
+        for(const auto sz = base_type::size(); first != last && base_type::free_list() != sz; ++first, base_type::swap_only_length_temporary_function(base_type::free_list() + 1u)) {
+            *first = base_type::operator[](base_type::free_list());
         }
 
         for(; first != last; ++first) {
-            *first = *base_type::try_emplace(entity_at(length++), true);
+            *first = *base_type::try_emplace(entity_at(base_type::free_list()), true);
+            base_type::swap_only_length_temporary_function(base_type::free_list() + 1u);
         }
     }
 
@@ -1189,15 +1168,15 @@ public:
      */
     template<typename It>
     size_type pack(It first, It last) {
-        size_type len = length;
+        size_type len = base_type::free_list();
 
         for(; first != last; ++first, --len) {
             const auto pos = base_type::index(*first);
-            ENTT_ASSERT(pos < length, "Invalid element");
+            ENTT_ASSERT(pos < base_type::free_list(), "Invalid element");
             base_type::swap_elements(base_type::data()[pos], base_type::data()[static_cast<size_type>(len - 1u)]);
         }
 
-        return (length - len);
+        return (base_type::free_list() - len);
     }
 
     /**
@@ -1205,7 +1184,7 @@ public:
      * @return The number of elements considered still in use.
      */
     [[nodiscard]] size_type in_use() const noexcept {
-        return length;
+        return base_type::free_list();
     }
 
     /**
@@ -1214,7 +1193,7 @@ public:
      */
     void in_use(const size_type len) noexcept {
         ENTT_ASSERT(!(len > base_type::size()), "Invalid length");
-        length = len;
+        base_type::swap_only_length_temporary_function(len);
     }
 
     /**
@@ -1225,12 +1204,12 @@ public:
      * @return An iterable object to use to _visit_ the storage.
      */
     [[nodiscard]] iterable each() noexcept {
-        return {internal::extended_storage_iterator{base_type::end() - length}, internal::extended_storage_iterator{base_type::end()}};
+        return {internal::extended_storage_iterator{base_type::end() - base_type::free_list()}, internal::extended_storage_iterator{base_type::end()}};
     }
 
     /*! @copydoc each */
     [[nodiscard]] const_iterable each() const noexcept {
-        return {internal::extended_storage_iterator{base_type::cend() - length}, internal::extended_storage_iterator{base_type::cend()}};
+        return {internal::extended_storage_iterator{base_type::cend() - base_type::free_list()}, internal::extended_storage_iterator{base_type::cend()}};
     }
 
     /**
@@ -1241,16 +1220,13 @@ public:
      * @return A reverse iterable object to use to _visit_ the storage.
      */
     [[nodiscard]] reverse_iterable reach() noexcept {
-        return {internal::extended_storage_iterator{base_type::rbegin()}, internal::extended_storage_iterator{base_type::rbegin() + length}};
+        return {internal::extended_storage_iterator{base_type::rbegin()}, internal::extended_storage_iterator{base_type::rbegin() + base_type::free_list()}};
     }
 
     /*! @copydoc reach */
     [[nodiscard]] const_reverse_iterable reach() const noexcept {
-        return {internal::extended_storage_iterator{base_type::crbegin()}, internal::extended_storage_iterator{base_type::crbegin() + length}};
+        return {internal::extended_storage_iterator{base_type::crbegin()}, internal::extended_storage_iterator{base_type::crbegin() + base_type::free_list()}};
     }
-
-private:
-    size_type length;
 };
 
 } // namespace entt