Skip to content

Commit

Permalink
sparse_set: swap-only mode for easy identification
Browse files Browse the repository at this point in the history
  • Loading branch information
skypjack committed Aug 21, 2023
1 parent 7178970 commit 0c8c321
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 3 deletions.
4 changes: 3 additions & 1 deletion src/entt/entity/fwd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ enum class deletion_policy : std::uint8_t {
/*! @brief Swap-and-pop deletion policy. */
swap_and_pop = 0u,
/*! @brief In-place deletion policy. */
in_place = 1u
in_place = 1u,
/*! @brief Swap-only deletion policy. */
swap_only = 2u
};

template<typename Entity = entity, typename = std::allocator<Entity>>
Expand Down
3 changes: 3 additions & 0 deletions src/entt/entity/sparse_set.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,9 @@ class basic_sparse_set {
in_place_pop(first);
}
break;
case deletion_policy::swap_only:
// no-op
break;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/entt/entity/storage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1035,7 +1035,7 @@ class basic_storage<Entity, Entity, Allocator>
* @param allocator The allocator to use.
*/
explicit basic_storage(const allocator_type &allocator)
: base_type{type_id<value_type>(), deletion_policy::swap_and_pop, allocator},
: base_type{type_id<value_type>(), deletion_policy::swap_only, allocator},
length{} {}

/**
Expand Down
96 changes: 96 additions & 0 deletions test/entt/entity/sparse_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,56 @@ TEST(SparseSet, CrossStableErase) {
ASSERT_EQ(set.data()[0u], entity[0u]);
}

TEST(SparseSet, SwapOnlyErase) {
using traits_type = entt::entt_traits<entt::entity>;

entt::sparse_set set{entt::deletion_policy::swap_only};
entt::entity entity[3u]{entt::entity{3}, entt::entity{42}, traits_type::construct(9, 3)};

ASSERT_EQ(set.policy(), entt::deletion_policy::swap_only);
ASSERT_TRUE(set.empty());

set.push(std::begin(entity), std::end(entity));
set.erase(set.begin(), set.end());

ASSERT_FALSE(set.empty());
ASSERT_EQ(set.size(), 3u);

set.erase(entity[2u]);

ASSERT_FALSE(set.empty());
ASSERT_EQ(set.size(), 3u);

ASSERT_EQ(set.at(0u), entity[0u]);
ASSERT_EQ(set.at(1u), entity[1u]);
ASSERT_EQ(set.at(2u), entity[2u]);
}

ENTT_DEBUG_TEST(SparseSetDeathTest, SwapOnlyErase) {
using traits_type = entt::entt_traits<entt::entity>;

entt::sparse_set set{entt::deletion_policy::swap_only};
entt::entity entity[2u]{entt::entity{42}, traits_type::construct(9, 3)};

ASSERT_DEATH(set.erase(std::begin(entity), std::end(entity)), "");
ASSERT_DEATH(set.erase(entt::null), "");
}

TEST(SparseSet, CrossSwapOnlyErase) {
entt::sparse_set set{entt::deletion_policy::swap_only};
entt::sparse_set other{entt::deletion_policy::swap_only};
entt::entity entity[2u]{entt::entity{3}, entt::entity{42}};

set.push(std::begin(entity), std::end(entity));
other.push(entity[1u]);
set.erase(other.begin(), other.end());

ASSERT_TRUE(set.contains(entity[0u]));
ASSERT_TRUE(set.contains(entity[1u]));
ASSERT_EQ(set.data()[0u], entity[0u]);
ASSERT_EQ(set.data()[1u], entity[1u]);
}

TEST(SparseSet, Remove) {
using traits_type = entt::entt_traits<entt::entity>;

Expand Down Expand Up @@ -810,6 +860,52 @@ TEST(SparseSet, CrossStableRemove) {
ASSERT_EQ(set.data()[0u], entity[0u]);
}

TEST(SparseSet, SwapOnlyRemove) {
using traits_type = entt::entt_traits<entt::entity>;

entt::sparse_set set{entt::deletion_policy::swap_only};
entt::entity entity[3u]{entt::entity{3}, entt::entity{42}, traits_type::construct(9, 3)};

ASSERT_EQ(set.policy(), entt::deletion_policy::swap_only);
ASSERT_TRUE(set.empty());

ASSERT_EQ(set.remove(std::begin(entity), std::end(entity)), 0u);
ASSERT_FALSE(set.remove(entity[1u]));

ASSERT_TRUE(set.empty());

set.push(std::begin(entity), std::end(entity));

ASSERT_EQ(set.remove(set.begin(), set.end()), 3u);
ASSERT_EQ(set.remove(set.begin(), set.end()), 3u);
ASSERT_FALSE(set.empty());
ASSERT_EQ(set.size(), 3u);

ASSERT_TRUE(set.remove(entity[2u]));
ASSERT_TRUE(set.remove(entity[2u]));
ASSERT_FALSE(set.empty());
ASSERT_EQ(set.size(), 3u);

ASSERT_EQ(set.at(0u), entity[0u]);
ASSERT_EQ(set.at(1u), entity[1u]);
ASSERT_EQ(set.at(2u), entity[2u]);
}

TEST(SparseSet, CrossSwapOnlyRemove) {
entt::sparse_set set{entt::deletion_policy::swap_only};
entt::sparse_set other{entt::deletion_policy::swap_only};
entt::entity entity[2u]{entt::entity{3}, entt::entity{42}};

set.push(std::begin(entity), std::end(entity));
other.push(entity[1u]);
set.remove(other.begin(), other.end());

ASSERT_TRUE(set.contains(entity[0u]));
ASSERT_TRUE(set.contains(entity[1u]));
ASSERT_EQ(set.data()[0u], entity[0u]);
ASSERT_EQ(set.data()[1u], entity[1u]);
}

TEST(SparseSet, Compact) {
entt::sparse_set set{entt::deletion_policy::in_place};

Expand Down
2 changes: 1 addition & 1 deletion test/entt/entity/storage_entity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ TEST(StorageEntity, TypeAndPolicy) {
entt::storage<entt::entity> pool;

ASSERT_EQ(pool.type(), entt::type_id<entt::entity>());
ASSERT_EQ(pool.policy(), entt::deletion_policy::swap_and_pop);
ASSERT_EQ(pool.policy(), entt::deletion_policy::swap_only);
}

TEST(StorageEntity, Functionalities) {
Expand Down

0 comments on commit 0c8c321

Please sign in to comment.