Browse Source

sparse_set: added the ::bump function

Michele Caini 4 years ago
parent
commit
efbb32a498
2 changed files with 44 additions and 2 deletions
  1. 16 2
      src/entt/entity/sparse_set.hpp
  2. 28 0
      test/entt/entity/sparse_set.cpp

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

@@ -172,10 +172,9 @@ template<typename Entity, typename Allocator>
 class basic_sparse_set {
     using alloc_traits = std::allocator_traits<Allocator>;
     static_assert(std::is_same_v<typename alloc_traits::value_type, Entity>);
-
-    using entity_traits = entt_traits<Entity>;
     using sparse_container_type = std::vector<typename alloc_traits::pointer, typename alloc_traits::template rebind_alloc<typename alloc_traits::pointer>>;
     using packed_container_type = std::vector<Entity, Allocator>;
+    using entity_traits = entt_traits<Entity>;
 
     [[nodiscard]] auto sparse_ptr(const Entity entt) const {
         const auto pos = static_cast<size_type>(entity_traits::to_entity(entt));
@@ -660,6 +659,21 @@ public:
         return try_emplace(entt, false, value);
     }
 
+    /**
+     * @brief Bump the version number of an entity.
+     *
+     * @warning
+     * Attempting to bump the version of an entity that doesn't belong to the
+     * sparse set results in undefined behavior.
+     *
+     * @param entt A valid identifier.
+     */
+    void bump(const entity_type entt) {
+        auto &entity = sparse_ref(entt);
+        entity = entity_traits::combine(entity_traits::to_integral(entity), entity_traits::to_integral(entt));
+        packed[static_cast<size_type>(entity_traits::to_entity(entity))] = entt;
+    }
+
     /**
      * @brief Assigns one or more entities to a sparse set.
      *

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

@@ -310,6 +310,34 @@ TEST(SparseSet, EmplaceOutOfBounds) {
     ASSERT_EQ(set.index(entities[1u]), 0u);
 }
 
+TEST(SparseSet, Bump) {
+    using traits_type = entt::entt_traits<entt::entity>;
+
+    entt::sparse_set set;
+    entt::entity entities[3u]{entt::entity{3}, entt::entity{42}, traits_type::construct(9, 3)};
+    set.insert(std::begin(entities), std::end(entities));
+
+    ASSERT_EQ(set.current(entities[0u]), 0u);
+    ASSERT_EQ(set.current(entities[1u]), 0u);
+    ASSERT_EQ(set.current(entities[2u]), 3u);
+
+    set.bump(entities[0u]);
+    set.bump(traits_type::construct(traits_type::to_entity(entities[1u]), 1));
+    set.bump(traits_type::construct(traits_type::to_entity(entities[2u]), 0));
+
+    ASSERT_EQ(set.current(entities[0u]), 0u);
+    ASSERT_EQ(set.current(entities[1u]), 1u);
+    ASSERT_EQ(set.current(entities[2u]), 0u);
+}
+
+TEST(SparseSetDeathTest, Bump) {
+    entt::sparse_set set{entt::deletion_policy::in_place};
+
+    ASSERT_DEATH(set.bump(entt::null), "");
+    ASSERT_DEATH(set.bump(entt::tombstone), "");
+    ASSERT_DEATH(set.bump(entt::entity{42}), "");
+}
+
 TEST(SparseSet, Insert) {
     entt::sparse_set set{entt::deletion_policy::in_place};
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};