sparse_set/storage: cleanup

This commit is contained in:
Michele Caini
2021-08-30 16:53:20 +02:00
parent d7b0fc09d7
commit d1a824f76e
2 changed files with 41 additions and 60 deletions

View File

@@ -197,44 +197,38 @@ class basic_sparse_set {
}
void resize_packed(const std::size_t req) {
auto &allocator = reserved.first();
auto &len = reserved.second();
ENTT_ASSERT((req != len) && !(req < count), "Invalid request");
const auto mem = alloc_traits::allocate(allocator, req);
ENTT_ASSERT((req != reserved.second()) && !(req < count), "Invalid request");
const auto mem = alloc_traits::allocate(reserved.first(), req);
std::uninitialized_fill(mem + count, mem + req, tombstone);
if(packed) {
std::uninitialized_copy(packed, packed + count, mem);
std::destroy(packed, packed + len);
alloc_traits::deallocate(allocator, packed, len);
std::destroy(packed, packed + reserved.second());
alloc_traits::deallocate(reserved.first(), packed, reserved.second());
}
packed = mem;
len = req;
reserved.second() = req;
}
void release_memory() {
auto &allocator = reserved.first();
auto &len = reserved.second();
if(packed) {
std::destroy(packed, packed + len);
alloc_traits::deallocate(allocator, packed, len);
std::destroy(packed, packed + reserved.second());
alloc_traits::deallocate(reserved.first(), packed, reserved.second());
}
if(sparse) {
alloc_ptr allocator_ptr{allocator};
for(size_type pos{}; pos < bucket; ++pos) {
if(sparse[pos]) {
std::destroy(sparse[pos], sparse[pos] + sparse_page_v);
alloc_traits::deallocate(allocator, sparse[pos], sparse_page_v);
alloc_traits::deallocate(reserved.first(), sparse[pos], sparse_page_v);
}
alloc_ptr_traits::destroy(allocator_ptr, std::addressof(sparse[pos]));
std::destroy_at(std::addressof(sparse[pos]));
}
alloc_ptr allocator_ptr{reserved.first()};
alloc_ptr_traits::deallocate(allocator_ptr, sparse, bucket);
}
}
@@ -316,9 +310,9 @@ protected:
ENTT_ASSERT(entity_traits::to_version(elem) == entity_traits::to_version(tombstone), "Slot not available");
if(free_list == null) {
if(const auto len = reserved.second(); count == len) {
const size_type sz = static_cast<size_type>(len * growth_factor_v);
resize_packed(sz + !(sz > len));
if(count == reserved.second()) {
const size_type sz = static_cast<size_type>(reserved.second() * growth_factor_v);
resize_packed(sz + !(sz > reserved.second()));
}
elem = entity_traits::combine(static_cast<typename entity_traits::entity_type>(count), entity_traits::to_integral(entt));

View File

@@ -199,36 +199,33 @@ class basic_storage: public basic_sparse_set<Entity, typename std::allocator_tra
const auto idx = pos / packed_page_v;
if(!(idx < bucket.second())) {
auto &allocator = bucket.first();
auto &len = bucket.second();
alloc_ptr allocator_ptr{allocator};
const size_type sz = idx + 1u;
alloc_ptr allocator_ptr{bucket.first()};
const auto mem = alloc_ptr_traits::allocate(allocator_ptr, sz);
std::uninitialized_value_construct(mem + len, mem + sz);
std::uninitialized_value_construct(mem + bucket.second(), mem + sz);
ENTT_TRY {
for(auto next = len; next < sz; ++next) {
mem[next] = alloc_traits::allocate(allocator, packed_page_v);
for(auto next = bucket.second(); next < sz; ++next) {
mem[next] = alloc_traits::allocate(bucket.first(), packed_page_v);
}
} ENTT_CATCH {
for(auto next = len; next < sz && mem[next]; ++next) {
alloc_traits::deallocate(allocator, mem[next], packed_page_v);
for(auto next = bucket.second(); next < sz && mem[next]; ++next) {
alloc_traits::deallocate(bucket.first(), mem[next], packed_page_v);
}
std::destroy(mem + len, mem + sz);
std::destroy(mem + bucket.second(), mem + sz);
alloc_ptr_traits::deallocate(allocator_ptr, mem, sz);
ENTT_THROW;
}
if(packed) {
std::uninitialized_copy(packed, packed + len, mem);
std::destroy(packed, packed + len);
alloc_ptr_traits::deallocate(allocator_ptr, packed, len);
std::uninitialized_copy(packed, packed + bucket.second(), mem);
std::destroy(packed, packed + bucket.second());
alloc_ptr_traits::deallocate(allocator_ptr, packed, bucket.second());
}
packed = mem;
len = sz;
bucket.second() = sz;
}
return packed[idx] + fast_mod<packed_page_v>(pos);
@@ -236,22 +233,19 @@ class basic_storage: public basic_sparse_set<Entity, typename std::allocator_tra
void release_unused_pages() {
if(const auto length = base_type::size() / packed_page_v; length < bucket.second()) {
auto &allocator = bucket.first();
auto &len = bucket.second();
alloc_ptr allocator_ptr{allocator};
alloc_ptr allocator_ptr{bucket.first()};
const auto mem = alloc_ptr_traits::allocate(allocator_ptr, length);
std::uninitialized_copy(packed, packed + length, mem);
for(auto pos = length; pos < len; ++pos) {
alloc_traits::deallocate(allocator, packed[pos], packed_page_v);
for(auto pos = length, last = bucket.second(); pos < last; ++pos) {
alloc_traits::deallocate(bucket.first(), packed[pos], packed_page_v);
}
std::destroy(packed, packed + len);
alloc_ptr_traits::deallocate(allocator_ptr, packed, len);
std::destroy(packed, packed + bucket.second());
alloc_ptr_traits::deallocate(allocator_ptr, packed, bucket.second());
packed = mem;
len = length;
bucket.second() = length;
}
}
@@ -262,20 +256,17 @@ class basic_storage: public basic_sparse_set<Entity, typename std::allocator_tra
base_type::clear();
} else {
for(size_type pos{}, last = base_type::size(); pos < last; ++pos) {
destroy(element_at(pos));
std::destroy_at(std::addressof(element_at(pos)));
}
}
auto &allocator = bucket.first();
auto &len = bucket.second();
alloc_ptr allocator_ptr{allocator};
for(size_type pos{}; pos < len; ++pos) {
alloc_traits::deallocate(allocator, packed[pos], packed_page_v);
alloc_ptr_traits::destroy(allocator_ptr, std::addressof(packed[pos]));
for(size_type pos{}, last = bucket.second(); pos < last; ++pos) {
alloc_traits::deallocate(bucket.first(), packed[pos], packed_page_v);
std::destroy_at(std::addressof(packed[pos]));
}
alloc_ptr_traits::deallocate(allocator_ptr, packed, len);
alloc_ptr allocator_ptr{bucket.first()};
alloc_ptr_traits::deallocate(allocator_ptr, packed, bucket.second());
}
}
@@ -288,10 +279,6 @@ class basic_storage: public basic_sparse_set<Entity, typename std::allocator_tra
}
}
void destroy(Type &elem) {
alloc_traits::destroy(bucket.first(), std::addressof(elem));
}
template<typename It, typename Generator>
void consume_range(It first, It last, Generator generator) {
for(const auto sz = base_type::size(); first != last && base_type::slot() != sz; ++first) {
@@ -337,7 +324,7 @@ protected:
void move_and_pop(const std::size_t from, const std::size_t to) final {
auto &elem = element_at(from);
construct(assure_at_least(to), std::move(elem));
destroy(elem);
std::destroy_at(std::addressof(elem));
}
/**
@@ -355,7 +342,7 @@ protected:
// support for nosy destructors
[[maybe_unused]] auto unused = std::move(target);
target = std::move(elem);
destroy(elem);
std::destroy_at(std::addressof(elem));
base_type::swap_and_pop(entt, ud);
}
@@ -369,7 +356,7 @@ protected:
const auto pos = base_type::index(entt);
base_type::in_place_pop(entt, ud);
// support for nosy destructors
destroy(element_at(pos));
std::destroy_at(std::addressof(element_at(pos)));
}
/**
@@ -386,7 +373,7 @@ protected:
base_type::try_emplace(entt, nullptr);
ENTT_ASSERT(pos == base_type::index(entt), "Misplaced component");
} ENTT_CATCH {
destroy(element_at(pos));
std::destroy_at(std::addressof(element_at(pos)));
ENTT_THROW;
}
}
@@ -684,7 +671,7 @@ public:
base_type::try_emplace(entt, nullptr);
ENTT_ASSERT(pos == base_type::index(entt), "Misplaced component");
} ENTT_CATCH {
destroy(element_at(pos));
std::destroy_at(std::addressof(element_at(pos)));
ENTT_THROW;
}