Kaynağa Gözat

sparse_set/storage: clear is backward compatible now

Michele Caini 3 yıl önce
ebeveyn
işleme
a425878e80

+ 0 - 2
TODO

@@ -16,8 +16,6 @@ TODO (high prio):
 * remove the static storage from the const assure in the registry
 * use sparse set iterator ::data to optimize range functionalities in the mixins and the registry (exploit the zero-check model)
 * can pass is_packed to clear_all to further optimize it in the derived classes
-* can add and hide-override pop_back to further optimize clearing a sparse set
-* maybe avoid clearing pages during a clear_all (for backward compatibility)?
 * review using std::swap usage, there are some mistakes here and there
 
 WIP:

+ 2 - 2
src/entt/entity/mixin.hpp

@@ -44,7 +44,7 @@ class sigh_mixin final: public Type {
         }
     }
 
-    void clear_all() final {
+    void pop_all() final {
         if(!destruction.empty()) {
             ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
 
@@ -61,7 +61,7 @@ class sigh_mixin final: public Type {
             }
         }
 
-        Type::clear_all();
+        Type::pop_all();
     }
 
     underlying_iterator try_emplace(const typename Type::entity_type entt, const bool force_back, const void *value) final {

+ 23 - 9
src/entt/entity/sparse_set.hpp

@@ -274,6 +274,13 @@ protected:
         packed[static_cast<size_type>(entt)] = std::exchange(free_list, traits_type::combine(entt, tombstone));
     }
 
+    /*! @brief Compact function for empty sparse sets. */
+    void fast_compact() {
+        ENTT_ASSERT((compact(), size()) == 0u, "Non-empty set");
+        packed.clear();
+        free_list = tombstone;
+    }
+
 protected:
     /**
      * @brief Erases entities from a sparse set.
@@ -293,11 +300,20 @@ protected:
     }
 
     /*! @brief Erases all entities of a sparse set. */
-    virtual void clear_all() {
-        release_sparse_pages();
-        sparse.clear();
-        packed.clear();
-        free_list = tombstone;
+    virtual void pop_all() {
+        if(mode == deletion_policy::swap_and_pop) {
+            for(auto first = begin(); !(first.index() < 0); ++first) {
+                swap_and_pop(first);
+            }
+        } else {
+            for(auto first = begin(); !(first.index() < 0); ++first) {
+                if(*first != tombstone) {
+                    in_place_pop(first);
+                }
+            }
+
+            fast_compact();
+        }
     }
 
     /**
@@ -817,7 +833,7 @@ public:
         return count;
     }
 
-    /*! @brief Removes all tombstones from the packed array of a sparse set. */
+    /*! @brief Removes all tombstones from a sparse set. */
     void compact() {
         size_type from = packed.size();
         for(; from && packed[from - 1u] == tombstone; --from) {}
@@ -968,9 +984,7 @@ public:
 
     /*! @brief Clears a sparse set. */
     void clear() {
-        if(!empty()) {
-            clear_all();
-        }
+        pop_all();
     }
 
     /**

+ 6 - 6
src/entt/entity/storage.hpp

@@ -350,22 +350,22 @@ protected:
     }
 
     /*! @brief Erases all entities of a storage. */
-    void clear_all() override {
+    void pop_all() override {
         for(auto first = base_type::begin(); !(first.index() < 0); ++first) {
-            const auto idx = static_cast<size_type>(first.index());
-
             if constexpr(traits_type::in_place_delete) {
                 if(*first != tombstone) {
                     base_type::in_place_pop(first);
-                    std::destroy_at(std::addressof(element_at(idx)));
+                    std::destroy_at(std::addressof(element_at(static_cast<size_type>(first.index()))));
                 }
             } else {
                 base_type::swap_and_pop(first);
-                std::destroy_at(std::addressof(element_at(idx)));
+                std::destroy_at(std::addressof(element_at(static_cast<size_type>(first.index()))));
             }
         }
 
-        base_type::clear_all();
+        if constexpr(traits_type::in_place_delete) {
+            base_type::fast_compact();
+        }
     }
 
     /**