Преглед изворни кода

sparse_set: faster remove/range-remove

Michele Caini пре 5 година
родитељ
комит
b9c33008d8
2 измењених фајлова са 25 додато и 44 уклоњено
  1. 16 11
      src/entt/entity/sparse_set.hpp
  2. 9 33
      src/entt/entity/storage.hpp

+ 16 - 11
src/entt/entity/sparse_set.hpp

@@ -174,6 +174,8 @@ class basic_sparse_set {
     }
 
     virtual void swap_at(const std::size_t, const std::size_t) {}
+    virtual void swap_and_pop(const std::size_t) {}
+    virtual void clear_all() {}
 
 public:
     /*! @brief Underlying entity identifier. */
@@ -419,14 +421,18 @@ public:
      *
      * @param entt A valid entity identifier.
      */
-    virtual void remove(const entity_type entt) {
+    void remove(const entity_type entt) {
         ENTT_ASSERT(contains(entt));
-        const auto curr = page(entt);
-        const auto pos = offset(entt);
-        packed[size_type{to_integral(sparse[curr][pos])}] = packed.back();
-        sparse[page(packed.back())][offset(packed.back())] = sparse[curr][pos];
-        sparse[curr][pos] = null;
+        auto &ref = sparse[page(entt)][offset(entt)];
+        const auto pos = size_type{to_integral(ref)};
+        const auto other = packed.back();
+
+        sparse[page(other)][offset(other)] = ref;
+        packed[pos] = other;
+        ref = null;
+
         packed.pop_back();
+        swap_and_pop(pos);
     }
 
     /**
@@ -463,9 +469,9 @@ public:
     void swap(const entity_type lhs, const entity_type rhs) {
         const auto from = index(lhs);
         const auto to = index(rhs);
-        swap_at(from, to);
         std::swap(sparse[page(lhs)][offset(lhs)], sparse[page(rhs)][offset(rhs)]);
         std::swap(packed[from], packed[to]);
+        swap_at(from, to);
     }
 
     /**
@@ -569,12 +575,11 @@ public:
         }
     }
 
-    /**
-     * @brief Clears a sparse set.
-     */
-    virtual void clear() ENTT_NOEXCEPT {
+    /*! @brief Clears a sparse set. */
+    void clear() ENTT_NOEXCEPT {
         sparse.clear();
         packed.clear();
+        clear_all();
     }
 
 private:

+ 9 - 33
src/entt/entity/storage.hpp

@@ -160,6 +160,15 @@ class basic_storage: public basic_sparse_set<Entity> {
         std::swap(instances[lhs], instances[rhs]);
     }
 
+    void swap_and_pop(const std::size_t pos) final {
+        instances[pos] = std::move(instances.back());
+        instances.pop_back();
+    }
+
+    void clear_all() ENTT_NOEXCEPT final {
+        instances.clear();
+    }
+
 public:
     /*! @brief Type of the objects associated with the entities. */
     using value_type = Type;
@@ -413,33 +422,6 @@ public:
         underlying_type::insert(first, last);
     }
 
-    /**
-     * @brief Removes an entity from a storage and destroys its object.
-     *
-     * @warning
-     * Attempting to use an entity that doesn't belong to the storage results in
-     * undefined behavior.
-     *
-     * @param entt A valid entity identifier.
-     */
-    void remove(const entity_type entt) final {
-        auto other = std::move(instances.back());
-        instances[underlying_type::index(entt)] = std::move(other);
-        instances.pop_back();
-        underlying_type::remove(entt);
-    }
-
-    /**
-     * @brief Removes multiple entities from a storage.
-     * @tparam It Type of input iterator.
-     * @param first An iterator to the first element of the range of entities.
-     * @param last An iterator past the last element of the range of entities.
-     */
-    template<typename It>
-    void remove(It first, It last) {
-        underlying_type::remove(first, last);
-    }
-
     /**
      * @brief Sort elements according to the given comparison function.
      *
@@ -503,12 +485,6 @@ public:
         sort_n(size(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
     }
 
-    /*! @brief Clears a storage. */
-    void clear() ENTT_NOEXCEPT final {
-        underlying_type::clear();
-        instances.clear();
-    }
-
 private:
     std::vector<value_type> instances;
 };