sparse_set: faster remove/range-remove

This commit is contained in:
Michele Caini
2020-11-05 11:53:54 +01:00
parent ca97f1c4a3
commit b9c33008d8
2 changed files with 25 additions and 44 deletions

View File

@@ -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:

View File

@@ -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;
};