|
|
@@ -967,7 +967,7 @@ class basic_storage<Entity, Entity, Allocator>
|
|
|
|
|
|
private:
|
|
|
void swap_or_move([[maybe_unused]] const std::size_t lhs, [[maybe_unused]] const std::size_t rhs) override {
|
|
|
- ENTT_ASSERT(((lhs < length) + (rhs < length)) != 1u, "Cross swapping is not supported");
|
|
|
+ ENTT_ASSERT(((lhs < base_type::free_list()) + (rhs < base_type::free_list())) != 1u, "Cross swapping is not supported");
|
|
|
}
|
|
|
|
|
|
protected:
|
|
|
@@ -978,24 +978,18 @@ protected:
|
|
|
*/
|
|
|
void pop(underlying_iterator first, underlying_iterator last) override {
|
|
|
for(; first != last; ++first) {
|
|
|
- if(const auto pos = base_type::index(*first); pos < length) {
|
|
|
+ if(const auto pos = base_type::index(*first); pos < base_type::free_list()) {
|
|
|
base_type::bump(local_traits_type::next(*first));
|
|
|
|
|
|
- if(const size_type slot = length - 1u; pos != slot) {
|
|
|
+ if(const size_type slot = base_type::free_list() - 1u; pos != slot) {
|
|
|
base_type::swap_elements(base_type::data()[pos], base_type::data()[slot]);
|
|
|
}
|
|
|
|
|
|
- --length;
|
|
|
+ base_type::swap_only_length_temporary_function(base_type::free_list() - 1u);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /*! @brief Erases all entities of a sparse set. */
|
|
|
- void pop_all() override {
|
|
|
- length = 0u;
|
|
|
- base_type::pop_all();
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* @brief Assigns an entity to a storage.
|
|
|
* @param hint A valid identifier.
|
|
|
@@ -1037,16 +1031,14 @@ public:
|
|
|
* @param allocator The allocator to use.
|
|
|
*/
|
|
|
explicit basic_storage(const allocator_type &allocator)
|
|
|
- : base_type{type_id<value_type>(), deletion_policy::swap_only, allocator},
|
|
|
- length{} {}
|
|
|
+ : base_type{type_id<value_type>(), deletion_policy::swap_only, allocator} {}
|
|
|
|
|
|
/**
|
|
|
* @brief Move constructor.
|
|
|
* @param other The instance to move from.
|
|
|
*/
|
|
|
basic_storage(basic_storage &&other) noexcept
|
|
|
- : base_type{std::move(other)},
|
|
|
- length{std::exchange(other.length, size_type{})} {}
|
|
|
+ : base_type{std::move(other)} {}
|
|
|
|
|
|
/**
|
|
|
* @brief Allocator-extended move constructor.
|
|
|
@@ -1054,8 +1046,7 @@ public:
|
|
|
* @param allocator The allocator to use.
|
|
|
*/
|
|
|
basic_storage(basic_storage &&other, const allocator_type &allocator) noexcept
|
|
|
- : base_type{std::move(other), allocator},
|
|
|
- length{std::exchange(other.length, size_type{})} {}
|
|
|
+ : base_type{std::move(other), allocator} {}
|
|
|
|
|
|
/**
|
|
|
* @brief Move assignment operator.
|
|
|
@@ -1064,7 +1055,6 @@ public:
|
|
|
*/
|
|
|
basic_storage &operator=(basic_storage &&other) noexcept {
|
|
|
base_type::operator=(std::move(other));
|
|
|
- length = std::exchange(other.length, size_type{});
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
@@ -1078,7 +1068,7 @@ public:
|
|
|
* @param entt A valid identifier.
|
|
|
*/
|
|
|
void get([[maybe_unused]] const entity_type entt) const noexcept {
|
|
|
- ENTT_ASSERT(base_type::index(entt) < length, "The requested entity is not a live one");
|
|
|
+ ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -1092,30 +1082,18 @@ public:
|
|
|
* @return Returns an empty tuple.
|
|
|
*/
|
|
|
[[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const noexcept {
|
|
|
- ENTT_ASSERT(base_type::index(entt) < length, "The requested entity is not a live one");
|
|
|
+ ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
|
|
|
return std::tuple{};
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * @brief Exchanges the contents with those of a given storage.
|
|
|
- * @param other Storage to exchange the content with.
|
|
|
- */
|
|
|
- void swap(basic_storage &other) {
|
|
|
- using std::swap;
|
|
|
- base_type::swap(other);
|
|
|
- swap(length, other.length);
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* @brief Creates a new identifier or recycles a destroyed one.
|
|
|
* @return A valid identifier.
|
|
|
*/
|
|
|
entity_type emplace() {
|
|
|
- if(length == base_type::size()) {
|
|
|
- return *base_type::try_emplace(entity_at(length++), true);
|
|
|
- }
|
|
|
-
|
|
|
- return base_type::operator[](length++);
|
|
|
+ const auto len = base_type::free_list();
|
|
|
+ base_type::swap_only_length_temporary_function(len + 1u);
|
|
|
+ return (len == base_type::size()) ? *base_type::try_emplace(entity_at(len), true) : base_type::operator[](len);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -1137,13 +1115,13 @@ public:
|
|
|
base_type::try_emplace(entity_at(base_type::size()), true);
|
|
|
}
|
|
|
|
|
|
- base_type::swap_elements(base_type::data()[pos], base_type::data()[length]);
|
|
|
- ++length;
|
|
|
- } else if(const auto idx = base_type::index(curr); idx < length) {
|
|
|
+ base_type::swap_elements(base_type::data()[pos], base_type::data()[base_type::free_list()]);
|
|
|
+ base_type::swap_only_length_temporary_function(base_type::free_list() + 1u);
|
|
|
+ } else if(const auto idx = base_type::index(curr); idx < base_type::free_list()) {
|
|
|
return emplace();
|
|
|
} else {
|
|
|
- base_type::swap_elements(base_type::data()[idx], base_type::data()[length]);
|
|
|
- ++length;
|
|
|
+ base_type::swap_elements(base_type::data()[idx], base_type::data()[base_type::free_list()]);
|
|
|
+ base_type::swap_only_length_temporary_function(base_type::free_list() + 1u);
|
|
|
}
|
|
|
|
|
|
base_type::bump(hint);
|
|
|
@@ -1171,12 +1149,13 @@ public:
|
|
|
*/
|
|
|
template<typename It>
|
|
|
void insert(It first, It last) {
|
|
|
- for(const auto sz = base_type::size(); first != last && length != sz; ++first, ++length) {
|
|
|
- *first = base_type::operator[](length);
|
|
|
+ for(const auto sz = base_type::size(); first != last && base_type::free_list() != sz; ++first, base_type::swap_only_length_temporary_function(base_type::free_list() + 1u)) {
|
|
|
+ *first = base_type::operator[](base_type::free_list());
|
|
|
}
|
|
|
|
|
|
for(; first != last; ++first) {
|
|
|
- *first = *base_type::try_emplace(entity_at(length++), true);
|
|
|
+ *first = *base_type::try_emplace(entity_at(base_type::free_list()), true);
|
|
|
+ base_type::swap_only_length_temporary_function(base_type::free_list() + 1u);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1189,15 +1168,15 @@ public:
|
|
|
*/
|
|
|
template<typename It>
|
|
|
size_type pack(It first, It last) {
|
|
|
- size_type len = length;
|
|
|
+ size_type len = base_type::free_list();
|
|
|
|
|
|
for(; first != last; ++first, --len) {
|
|
|
const auto pos = base_type::index(*first);
|
|
|
- ENTT_ASSERT(pos < length, "Invalid element");
|
|
|
+ ENTT_ASSERT(pos < base_type::free_list(), "Invalid element");
|
|
|
base_type::swap_elements(base_type::data()[pos], base_type::data()[static_cast<size_type>(len - 1u)]);
|
|
|
}
|
|
|
|
|
|
- return (length - len);
|
|
|
+ return (base_type::free_list() - len);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -1205,7 +1184,7 @@ public:
|
|
|
* @return The number of elements considered still in use.
|
|
|
*/
|
|
|
[[nodiscard]] size_type in_use() const noexcept {
|
|
|
- return length;
|
|
|
+ return base_type::free_list();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -1214,7 +1193,7 @@ public:
|
|
|
*/
|
|
|
void in_use(const size_type len) noexcept {
|
|
|
ENTT_ASSERT(!(len > base_type::size()), "Invalid length");
|
|
|
- length = len;
|
|
|
+ base_type::swap_only_length_temporary_function(len);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -1225,12 +1204,12 @@ public:
|
|
|
* @return An iterable object to use to _visit_ the storage.
|
|
|
*/
|
|
|
[[nodiscard]] iterable each() noexcept {
|
|
|
- return {internal::extended_storage_iterator{base_type::end() - length}, internal::extended_storage_iterator{base_type::end()}};
|
|
|
+ return {internal::extended_storage_iterator{base_type::end() - base_type::free_list()}, internal::extended_storage_iterator{base_type::end()}};
|
|
|
}
|
|
|
|
|
|
/*! @copydoc each */
|
|
|
[[nodiscard]] const_iterable each() const noexcept {
|
|
|
- return {internal::extended_storage_iterator{base_type::cend() - length}, internal::extended_storage_iterator{base_type::cend()}};
|
|
|
+ return {internal::extended_storage_iterator{base_type::cend() - base_type::free_list()}, internal::extended_storage_iterator{base_type::cend()}};
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -1241,16 +1220,13 @@ public:
|
|
|
* @return A reverse iterable object to use to _visit_ the storage.
|
|
|
*/
|
|
|
[[nodiscard]] reverse_iterable reach() noexcept {
|
|
|
- return {internal::extended_storage_iterator{base_type::rbegin()}, internal::extended_storage_iterator{base_type::rbegin() + length}};
|
|
|
+ return {internal::extended_storage_iterator{base_type::rbegin()}, internal::extended_storage_iterator{base_type::rbegin() + base_type::free_list()}};
|
|
|
}
|
|
|
|
|
|
/*! @copydoc reach */
|
|
|
[[nodiscard]] const_reverse_iterable reach() const noexcept {
|
|
|
- return {internal::extended_storage_iterator{base_type::crbegin()}, internal::extended_storage_iterator{base_type::crbegin() + length}};
|
|
|
+ return {internal::extended_storage_iterator{base_type::crbegin()}, internal::extended_storage_iterator{base_type::crbegin() + base_type::free_list()}};
|
|
|
}
|
|
|
-
|
|
|
-private:
|
|
|
- size_type length;
|
|
|
};
|
|
|
|
|
|
} // namespace entt
|