Browse Source

sparse_set: pop_at(pos) -> try_erase(entt) (prepare for inhibited deletions)

Michele Caini 4 years ago
parent
commit
0bd6816bdd
2 changed files with 18 additions and 16 deletions
  1. 10 7
      src/entt/entity/sparse_set.hpp
  2. 8 9
      src/entt/entity/storage.hpp

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

@@ -234,21 +234,23 @@ private:
 protected:
     /**
      * @brief Erases an entity from a sparse set.
-     * @param pos A valid position of an element within a sparse set.
+     * @param entt A valid identifier.
      */
-    virtual void pop_at(const std::size_t pos) {
+    virtual void try_erase(const Entity entt) {
+        const auto pos = index(entt);
+
         if(mode == deletion_policy::in_place) {
-            sparse_ref(packed[pos]) = null;
             packed[pos] = std::exchange(free_list, entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), entity_traits::reserved));
         } else {
-            sparse_ref(packed.back()) = entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), entity_traits::to_integral(packed.back()));
-            // lazy self-assignment guard
-            sparse_ref(packed[pos]) = null;
             packed[pos] = packed.back();
+            sparse_ref(packed.back()) = entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), entity_traits::to_integral(packed.back()));
             // unnecessary but it helps to detect nasty bugs
             ENTT_ASSERT((packed.back() = tombstone, true), "");
             packed.pop_back();
         }
+
+        // lazy self-assignment guard
+        sparse_ref(entt) = null;
     }
 
     /**
@@ -692,7 +694,8 @@ public:
      * @param entt A valid identifier.
      */
     void erase(const entity_type entt) {
-        pop_at(index(entt));
+        ENTT_ASSERT(contains(entt), "Set does not contain entity");
+        try_erase(entt);
         ENTT_ASSERT(!contains(entt), "Destruction did not take place");
     }
 

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

@@ -324,18 +324,18 @@ private:
 protected:
     /**
      * @brief Erases an element from a storage.
-     * @param pos A valid position of an element within a storage.
+     * @param entt A valid identifier.
      */
-    void pop_at(const std::size_t pos) override {
+    void try_erase(const Entity entt) override {
         if constexpr(comp_traits::in_place_delete) {
-            std::destroy_at(std::addressof(element_at(pos)));
-            base_type::pop_at(pos);
+            std::destroy_at(std::addressof(element_at(base_type::index(entt))));
+            base_type::try_erase(entt);
         } else {
             auto &elem = element_at(base_type::size() - 1u);
             // support chained destructors i.e. parent-to-child propagation
-            [[maybe_unused]] auto unused = std::exchange(element_at(pos), std::move(elem));
+            [[maybe_unused]] auto unused = std::exchange(element_at(base_type::index(entt)), std::move(elem));
             std::destroy_at(std::addressof(elem));
-            base_type::pop_at(pos);
+            base_type::try_erase(entt);
         }
     }
 
@@ -906,11 +906,10 @@ public:
  */
 template<typename Type>
 class sigh_storage_mixin final: public Type {
-    void pop_at(const std::size_t pos) final {
+    void try_erase(const typename Type::entity_type entt) final {
         ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
-        const auto entt = Type::operator[](pos);
         destruction.publish(*owner, entt);
-        Type::pop_at(Type::index(entt));
+        Type::try_erase(entt);
     }
 
     void try_emplace(const typename Type::entity_type entt, const void *value) final {