Browse Source

sparse_set: added the possibility to change the deletion policy at runtime

Michele Caini 4 years ago
parent
commit
8eaf11b510
3 changed files with 91 additions and 0 deletions
  1. 12 0
      src/entt/entity/sparse_set.hpp
  2. 36 0
      test/entt/entity/sparse_set.cpp
  3. 43 0
      test/entt/entity/storage.cpp

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

@@ -411,6 +411,18 @@ public:
         return mode;
     }
 
+    /**
+     * @brief Sets the deletion policy of a sparse set.
+     * @param pol The deletion policy of the sparse set.
+     */
+    void policy(const deletion_policy pol) ENTT_NOEXCEPT {
+        if(pol != mode && mode == deletion_policy::in_place) {
+            compact();
+        }
+
+        mode = pol;
+    }
+
     /**
      * @brief Returns the next slot available for insertion.
      * @return The next slot available for insertion.

+ 36 - 0
test/entt/entity/sparse_set.cpp

@@ -753,6 +753,42 @@ TEST(SparseSet, Compact) {
     ASSERT_TRUE(set.empty());
 }
 
+TEST(SparseSet, Policy) {
+    entt::sparse_set set{entt::deletion_policy::in_place};
+    entt::entity entities[3u]{entt::entity{0}, entt::entity{1}, entt::entity{2}};
+
+    set.insert(std::begin(entities), std::end(entities));
+    set.erase(entities[1u]);
+
+    ASSERT_EQ(set.size(), 3u);
+    ASSERT_EQ(set.index(entities[0u]), 0u);
+    ASSERT_FALSE(set.contains(entities[1u]));
+    ASSERT_EQ(set.index(entities[2u]), 2u);
+
+    set.policy(entt::deletion_policy::swap_and_pop);
+
+    ASSERT_EQ(set.size(), 2u);
+    ASSERT_EQ(set.index(entities[0u]), 0u);
+    ASSERT_EQ(set.index(entities[2u]), 1u);
+
+    set.erase(entities[0u]);
+
+    ASSERT_EQ(set.size(), 1u);
+    ASSERT_FALSE(set.contains(entities[0u]));
+    ASSERT_EQ(set.index(entities[2u]), 0u);
+
+    set.policy(entt::deletion_policy::in_place);
+    set.erase(entities[2u]);
+
+    ASSERT_EQ(set.size(), 1u);
+    ASSERT_FALSE(set.contains(entities[2u]));
+
+    set.policy(entt::deletion_policy::swap_and_pop);
+
+    ASSERT_EQ(set.size(), 0u);
+    ASSERT_TRUE(set.empty());
+}
+
 TEST(SparseSet, SwapEntity) {
     using traits_type = entt::entt_traits<entt::entity>;
 

+ 43 - 0
test/entt/entity/storage.cpp

@@ -772,6 +772,49 @@ TEST(Storage, Compact) {
     ASSERT_TRUE(pool.empty());
 }
 
+TEST(Storage, Policy) {
+    entt::storage<stable_type> pool{};
+    entt::entity entities[3u]{entt::entity{0}, entt::entity{1}, entt::entity{2}};
+
+    pool.emplace(entities[0u], stable_type{0});
+    pool.emplace(entities[1u], stable_type{1});
+    pool.emplace(entities[2u], stable_type{2});
+    pool.erase(entities[1u]);
+
+    ASSERT_EQ(pool.size(), 3u);
+    ASSERT_EQ(pool.index(entities[0u]), 0u);
+    ASSERT_FALSE(pool.contains(entities[1u]));
+    ASSERT_EQ(pool.index(entities[2u]), 2u);
+    ASSERT_EQ(pool.get(entities[0u]).value, 0);
+    ASSERT_EQ(pool.get(entities[2u]).value, 2);
+
+    pool.policy(entt::deletion_policy::swap_and_pop);
+
+    ASSERT_EQ(pool.size(), 2u);
+    ASSERT_EQ(pool.index(entities[0u]), 0u);
+    ASSERT_EQ(pool.index(entities[2u]), 1u);
+    ASSERT_EQ(pool.get(entities[0u]).value, 0);
+    ASSERT_EQ(pool.get(entities[2u]).value, 2);
+
+    pool.erase(entities[0u]);
+
+    ASSERT_EQ(pool.size(), 1u);
+    ASSERT_FALSE(pool.contains(entities[0u]));
+    ASSERT_EQ(pool.index(entities[2u]), 0u);
+    ASSERT_EQ(pool.get(entities[2u]).value, 2);
+
+    pool.policy(entt::deletion_policy::in_place);
+    pool.erase(entities[2u]);
+
+    ASSERT_EQ(pool.size(), 1u);
+    ASSERT_FALSE(pool.contains(entities[2u]));
+
+    pool.policy(entt::deletion_policy::swap_and_pop);
+
+    ASSERT_EQ(pool.size(), 0u);
+    ASSERT_TRUE(pool.empty());
+}
+
 TEST(Storage, ShrinkToFit) {
     entt::storage<int> pool;