Bladeren bron

sparse_set: minor changes

Michele Caini 4 jaren geleden
bovenliggende
commit
86414671d6
2 gewijzigde bestanden met toevoegingen van 83 en 81 verwijderingen
  1. 1 0
      TODO
  2. 82 81
      src/entt/entity/sparse_set.hpp

+ 1 - 0
TODO

@@ -4,6 +4,7 @@
 * add examples (and credits) from @alanjfs :)
 
 WIP:
+* decouple storage iterator from allocator
 * fast-contains for sparse sets (low prio but nice-to-have)
 * runtime components (registry), runtime events (dispatcher/emitter), runtime context variables ...
 * runtime_view/registry, remove reference to basic_sparse_set<E>

+ 82 - 81
src/entt/entity/sparse_set.hpp

@@ -32,13 +32,13 @@ struct sparse_set_iterator final {
     using value_type = typename Traits::value_type;
     using pointer = typename Traits::pointer;
     using reference = typename Traits::reference;
-    using difference_type = typename entt_traits<value_type>::difference_type;
+    using difference_type = typename Traits::difference_type;
     using iterator_category = std::random_access_iterator_tag;
 
     sparse_set_iterator() ENTT_NOEXCEPT = default;
 
     sparse_set_iterator(const pointer *ref, const difference_type idx) ENTT_NOEXCEPT
-        : packed_array{ref},
+        : packed{ref},
           index{idx}
     {}
 
@@ -84,7 +84,7 @@ struct sparse_set_iterator final {
 
     [[nodiscard]] reference operator[](const difference_type value) const {
         const auto pos = index - value - 1;
-        return (*packed_array)[pos];
+        return (*packed)[pos];
     }
 
     [[nodiscard]] bool operator==(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
@@ -113,7 +113,7 @@ struct sparse_set_iterator final {
 
     [[nodiscard]] pointer operator->() const {
         const auto pos = index - 1;
-        return (*packed_array) + pos;
+        return (*packed) + pos;
     }
 
     [[nodiscard]] reference operator*() const {
@@ -121,7 +121,7 @@ struct sparse_set_iterator final {
     }
 
 private:
-    const pointer *packed_array;
+    const pointer *packed;
     difference_type index;
 };
 
@@ -201,25 +201,25 @@ class basic_sparse_set {
 
             std::uninitialized_value_construct(mem + bucket, mem + sz);
 
-            if(sparse_array) {
-                std::uninitialized_copy(sparse_array, sparse_array + bucket, mem);
-                std::destroy(sparse_array, sparse_array + bucket);
-                alloc_ptr_traits::deallocate(allocator_ptr, sparse_array, bucket);
+            if(sparse) {
+                std::uninitialized_copy(sparse, sparse + bucket, mem);
+                std::destroy(sparse, sparse + bucket);
+                alloc_ptr_traits::deallocate(allocator_ptr, sparse, bucket);
             }
 
-            sparse_array = mem;
+            sparse = mem;
             bucket = sz;
         }
 
-        if(!sparse_array[idx]) {
-            sparse_array[idx] = alloc_traits::allocate(reserved.first(), sparse_page_v);
-            std::uninitialized_fill(sparse_array[idx], sparse_array[idx] + sparse_page_v, null);
+        if(!sparse[idx]) {
+            sparse[idx] = alloc_traits::allocate(reserved.first(), sparse_page_v);
+            std::uninitialized_fill(sparse[idx], sparse[idx] + sparse_page_v, null);
         }
 
-        return sparse_array[idx];
+        return sparse[idx];
     }
 
-    void resize_packed_array(const std::size_t req) {
+    void resize_packed(const std::size_t req) {
         auto &allocator = reserved.first();
         auto &len = reserved.second();
         ENTT_ASSERT((req != len) && !(req < count), "Invalid request");
@@ -227,13 +227,13 @@ class basic_sparse_set {
 
         std::uninitialized_fill(mem + count, mem + req, tombstone);
 
-        if(packed_array) {
-            std::uninitialized_copy(packed_array, packed_array + count, mem);
-            std::destroy(packed_array, packed_array + len);
-            alloc_traits::deallocate(allocator, packed_array, len);
+        if(packed) {
+            std::uninitialized_copy(packed, packed + count, mem);
+            std::destroy(packed, packed + len);
+            alloc_traits::deallocate(allocator, packed, len);
         }
 
-        packed_array = mem;
+        packed = mem;
         len = req;
     }
 
@@ -241,24 +241,24 @@ class basic_sparse_set {
         auto &allocator = reserved.first();
         auto &len = reserved.second();
 
-        if(packed_array) {
-            std::destroy(packed_array, packed_array + len);
-            alloc_traits::deallocate(allocator, packed_array, len);
+        if(packed) {
+            std::destroy(packed, packed + len);
+            alloc_traits::deallocate(allocator, packed, len);
         }
 
-        if(sparse_array) {
+        if(sparse) {
             alloc_ptr allocator_ptr{allocator};
 
             for(size_type pos{}; pos < bucket; ++pos) {
-                if(sparse_array[pos]) {
-                    std::destroy(sparse_array[pos], sparse_array[pos] + sparse_page_v);
-                    alloc_traits::deallocate(allocator, sparse_array[pos], sparse_page_v);
+                if(sparse[pos]) {
+                    std::destroy(sparse[pos], sparse[pos] + sparse_page_v);
+                    alloc_traits::deallocate(allocator, sparse[pos], sparse_page_v);
                 }
 
-                alloc_ptr_traits::destroy(allocator_ptr, std::addressof(sparse_array[pos]));
+                alloc_ptr_traits::destroy(allocator_ptr, std::addressof(sparse[pos]));
             }
 
-            alloc_ptr_traits::deallocate(allocator_ptr, sparse_array, bucket);
+            alloc_ptr_traits::deallocate(allocator_ptr, sparse, bucket);
         }
     }
 
@@ -277,13 +277,13 @@ protected:
      * @param entt A valid identifier.
      */
     virtual void swap_and_pop(const Entity entt, void *) {
-        auto &ref = sparse_array[page(entt)][offset(entt)];
+        auto &ref = sparse[page(entt)][offset(entt)];
         const auto pos = static_cast<size_type>(entity_traits::to_entity(ref));
-        ENTT_ASSERT(packed_array[pos] == entt, "Invalid identifier");
-        auto &last = packed_array[--count];
+        ENTT_ASSERT(packed[pos] == entt, "Invalid identifier");
+        auto &last = packed[--count];
 
-        packed_array[pos] = last;
-        auto &elem = sparse_array[page(last)][offset(last)];
+        packed[pos] = last;
+        auto &elem = sparse[page(last)][offset(last)];
         elem = entity_traits::combine(entity_traits::to_integral(ref), entity_traits::to_integral(elem));
         // lazy self-assignment guard
         ref = null;
@@ -296,11 +296,11 @@ protected:
      * @param entt A valid identifier.
      */
     virtual void in_place_pop(const Entity entt, void *) {
-        auto &ref = sparse_array[page(entt)][offset(entt)];
+        auto &ref = sparse[page(entt)][offset(entt)];
         const auto pos = static_cast<size_type>(entity_traits::to_entity(ref));
-        ENTT_ASSERT(packed_array[pos] == entt, "Invalid identifier");
+        ENTT_ASSERT(packed[pos] == entt, "Invalid identifier");
 
-        packed_array[pos] = std::exchange(free_list, entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), entity_traits::reserved));
+        packed[pos] = std::exchange(free_list, entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), entity_traits::reserved));
         // lazy self-assignment guard
         ref = null;
     }
@@ -315,14 +315,14 @@ protected:
         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_array(sz + !(sz > len));
+                resize_packed(sz + !(sz > len));
             }
 
             assure_page(page(entt))[offset(entt)] = entity_traits::combine(static_cast<typename entity_traits::entity_type>(count), entity_traits::to_integral(entt));
-            packed_array[count++] = entt;
+            packed[count++] = entt;
         } else {
             assure_page(page(entt))[offset(entt)] = entity_traits::combine(entity_traits::to_integral(free_list), entity_traits::to_integral(entt));
-            free_list = std::exchange(packed_array[static_cast<size_type>(entity_traits::to_entity(free_list))], entt);
+            free_list = std::exchange(packed[static_cast<size_type>(entity_traits::to_entity(free_list))], entt);
         }
     }
 
@@ -362,8 +362,8 @@ public:
      */
     explicit basic_sparse_set(deletion_policy pol, const allocator_type &allocator = {})
         : reserved{allocator, size_type{}},
-          sparse_array{},
-          packed_array{},
+          sparse{},
+          packed{},
           bucket{},
           count{},
           free_list{tombstone},
@@ -376,8 +376,8 @@ public:
      */
     basic_sparse_set(basic_sparse_set &&other) ENTT_NOEXCEPT
         : reserved{std::move(other.reserved.first()), std::exchange(other.reserved.second(), size_type{})},
-          sparse_array{std::exchange(other.sparse_array, alloc_ptr_pointer{})},
-          packed_array{std::exchange(other.packed_array, alloc_pointer{})},
+          sparse{std::exchange(other.sparse, alloc_ptr_pointer{})},
+          packed{std::exchange(other.packed, alloc_pointer{})},
           bucket{std::exchange(other.bucket, size_type{})},
           count{std::exchange(other.count, size_type{})},
           free_list{std::exchange(other.free_list, tombstone)},
@@ -391,8 +391,8 @@ public:
      */
     basic_sparse_set(basic_sparse_set &&other, const allocator_type &allocator) ENTT_NOEXCEPT
         : reserved{allocator, std::exchange(other.reserved.second(), size_type{})},
-          sparse_array{std::exchange(other.sparse_array, alloc_ptr_pointer{})},
-          packed_array{std::exchange(other.packed_array, alloc_pointer{})},
+          sparse{std::exchange(other.sparse, alloc_ptr_pointer{})},
+          packed{std::exchange(other.packed, alloc_pointer{})},
           bucket{std::exchange(other.bucket, size_type{})},
           count{std::exchange(other.count, size_type{})},
           free_list{std::exchange(other.free_list, tombstone)},
@@ -416,8 +416,8 @@ public:
         propagate_on_container_move_assignment(reserved.first(), other.reserved.first());
         ENTT_ASSERT(alloc_traits::is_always_equal::value || reserved.first() == other.reserved.first(), "Copying a sparse set is not allowed");
         reserved.second() = std::exchange(other.reserved.second(), size_type{});
-        sparse_array = std::exchange(other.sparse_array, alloc_ptr_pointer{});
-        packed_array = std::exchange(other.packed_array, alloc_pointer{});
+        sparse = std::exchange(other.sparse, alloc_ptr_pointer{});
+        packed = std::exchange(other.packed, alloc_pointer{});
         bucket = std::exchange(other.bucket, size_type{});
         count = std::exchange(other.count, size_type{});
         free_list = std::exchange(other.free_list, tombstone);
@@ -434,8 +434,8 @@ public:
         swap_contents(other);
         propagate_on_container_swap(reserved.first(), other.reserved.first());
         swap(reserved.second(), other.reserved.second());
-        swap(sparse_array, other.sparse_array);
-        swap(packed_array, other.packed_array);
+        swap(sparse, other.sparse);
+        swap(packed, other.packed);
         swap(bucket, other.bucket);
         swap(count, other.count);
         swap(free_list, other.free_list);
@@ -476,7 +476,7 @@ public:
      */
     virtual void reserve(const size_type cap) {
         if(cap > reserved.second()) {
-            resize_packed_array(cap);
+            resize_packed(cap);
         }
     }
 
@@ -492,7 +492,7 @@ public:
     /*! @brief Requests the removal of unused capacity. */
     virtual void shrink_to_fit() {
         if(count < reserved.second()) {
-            resize_packed_array(count);
+            resize_packed(count);
         }
     }
 
@@ -537,7 +537,7 @@ public:
      * @return A pointer to the internal packed array.
      */
     [[nodiscard]] pointer data() const ENTT_NOEXCEPT {
-        return packed_array;
+        return packed;
     }
 
     /**
@@ -550,7 +550,8 @@ public:
      * @return An iterator to the first entity of the sparse set.
      */
     [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
-        return iterator{std::addressof(packed_array), static_cast<typename entity_traits::difference_type>(count)};
+        const auto pos = static_cast<typename entity_traits::difference_type>(count);
+        return iterator{std::addressof(packed), pos};
     }
 
     /**
@@ -564,7 +565,7 @@ public:
      * set.
      */
     [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
-        return iterator{std::addressof(packed_array), {}};
+        return iterator{std::addressof(packed), {}};
     }
 
     /**
@@ -611,10 +612,10 @@ public:
      * @return True if the sparse set contains the entity, false otherwise.
      */
     [[nodiscard]] bool contains(const entity_type entt) const ENTT_NOEXCEPT {
-        if(const auto curr = page(entt); curr < bucket && sparse_array[curr]) {
+        if(const auto curr = page(entt); curr < bucket && sparse[curr]) {
             constexpr auto cap = entity_traits::to_entity(entt::null);
             // testing versions permits to avoid accessing the packed array
-            return (((~cap & entity_traits::to_integral(entt)) ^ entity_traits::to_integral(sparse_array[curr][offset(entt)])) < cap);
+            return (((~cap & entity_traits::to_integral(entt)) ^ entity_traits::to_integral(sparse[curr][offset(entt)])) < cap);
         }
 
         return false;
@@ -627,8 +628,8 @@ public:
      * version otherwise.
      */
     [[nodiscard]] version_type current(const entity_type entt) const {
-        if(const auto curr = page(entt); curr < bucket && sparse_array[curr]) {
-            return entity_traits::to_version(sparse_array[curr][offset(entt)]);
+        if(const auto curr = page(entt); curr < bucket && sparse[curr]) {
+            return entity_traits::to_version(sparse[curr][offset(entt)]);
         }
 
         return entity_traits::to_version(tombstone);
@@ -646,7 +647,7 @@ public:
      */
     [[nodiscard]] size_type index(const entity_type entt) const ENTT_NOEXCEPT {
         ENTT_ASSERT(contains(entt), "Set does not contain entity");
-        return static_cast<size_type>(entity_traits::to_entity(sparse_array[page(entt)][offset(entt)]));
+        return static_cast<size_type>(entity_traits::to_entity(sparse[page(entt)][offset(entt)]));
     }
 
     /**
@@ -655,7 +656,7 @@ public:
      * @return The entity at specified location if any, a null entity otherwise.
      */
     [[nodiscard]] entity_type at(const size_type pos) const ENTT_NOEXCEPT {
-        return pos < count ? packed_array[pos] : null;
+        return pos < count ? packed[pos] : null;
     }
 
     /**
@@ -665,7 +666,7 @@ public:
      */
     [[nodiscard]] entity_type operator[](const size_type pos) const ENTT_NOEXCEPT {
         ENTT_ASSERT(pos < count, "Position is out of bounds");
-        return packed_array[pos];
+        return packed[pos];
     }
 
     /**
@@ -773,17 +774,17 @@ public:
     /*! @brief Removes all tombstones from the packed array of a sparse set. */
     void compact() {
         size_type next = count;
-        for(; next && packed_array[next - 1u] == tombstone; --next);
+        for(; next && packed[next - 1u] == tombstone; --next);
 
-        for(auto *it = &free_list; *it != null && next; it = std::addressof(packed_array[entity_traits::to_entity(*it)])) {
+        for(auto *it = &free_list; *it != null && next; it = std::addressof(packed[entity_traits::to_entity(*it)])) {
             if(const size_type pos = entity_traits::to_entity(*it); pos < next) {
                 --next;
                 move_and_pop(next, pos);
-                std::swap(packed_array[next], packed_array[pos]);
+                std::swap(packed[next], packed[pos]);
                 const auto entity = static_cast<typename entity_traits::entity_type>(pos);
-                sparse_array[page(packed_array[pos])][offset(packed_array[pos])] = entity_traits::combine(entity, entity_traits::to_integral(packed_array[pos]));
+                sparse[page(packed[pos])][offset(packed[pos])] = entity_traits::combine(entity, entity_traits::to_integral(packed[pos]));
                 *it = entity_traits::combine(static_cast<typename entity_traits::entity_type>(next), entity_traits::reserved);
-                for(; next && packed_array[next - 1u] == tombstone; --next);
+                for(; next && packed[next - 1u] == tombstone; --next);
             }
         }
 
@@ -807,17 +808,17 @@ public:
     void swap_elements(const entity_type lhs, const entity_type rhs) {
         ENTT_ASSERT(contains(lhs) && contains(rhs), "Set does not contain entities");
 
-        auto &entt = sparse_array[page(lhs)][offset(lhs)];
-        auto &other = sparse_array[page(rhs)][offset(rhs)];
+        auto &entt = sparse[page(lhs)][offset(lhs)];
+        auto &other = sparse[page(rhs)][offset(rhs)];
 
         const auto from = entity_traits::to_entity(entt);
         const auto to = entity_traits::to_entity(other);
 
         // basic no-leak guarantee (with invalid state) if swapping throws
         swap_at(static_cast<size_type>(from), static_cast<size_type>(to));
-        entt = entity_traits::combine(to, entity_traits::to_integral(packed_array[from]));
-        other = entity_traits::combine(from, entity_traits::to_integral(packed_array[to]));
-        std::swap(packed_array[from], packed_array[to]);
+        entt = entity_traits::combine(to, entity_traits::to_integral(packed[from]));
+        other = entity_traits::combine(from, entity_traits::to_integral(packed[to]));
+        std::swap(packed[from], packed[to]);
     }
 
     /**
@@ -856,19 +857,19 @@ public:
         ENTT_ASSERT(!(length > count), "Length exceeds the number of elements");
         compact();
 
-        algo(std::make_reverse_iterator(packed_array + length), std::make_reverse_iterator(packed_array), std::move(compare), std::forward<Args>(args)...);
+        algo(std::make_reverse_iterator(packed + length), std::make_reverse_iterator(packed), std::move(compare), std::forward<Args>(args)...);
 
         for(size_type pos{}; pos < length; ++pos) {
             auto curr = pos;
-            auto next = index(packed_array[curr]);
+            auto next = index(packed[curr]);
 
             while(curr != next) {
-                const auto idx = index(packed_array[next]);
-                const auto entt = packed_array[curr];
+                const auto idx = index(packed[next]);
+                const auto entt = packed[curr];
 
                 swap_at(next, idx);
                 const auto entity = static_cast<typename entity_traits::entity_type>(curr);
-                sparse_array[page(entt)][offset(entt)] = entity_traits::combine(entity, entity_traits::to_integral(packed_array[curr]));
+                sparse[page(entt)][offset(entt)] = entity_traits::combine(entity, entity_traits::to_integral(packed[curr]));
                 curr = std::exchange(next, idx);
             }
         }
@@ -914,9 +915,9 @@ public:
 
         for(size_type pos = count - 1; pos && from != to; ++from) {
             if(contains(*from)) {
-                if(*from != packed_array[pos]) {
+                if(*from != packed[pos]) {
                     // basic no-leak guarantee (with invalid state) if swapping throws
-                    swap_elements(packed_array[pos], *from);
+                    swap_elements(packed[pos], *from);
                 }
 
                 --pos;
@@ -937,8 +938,8 @@ public:
 
 private:
     compressed_pair<alloc, size_type> reserved;
-    alloc_ptr_pointer sparse_array;
-    alloc_pointer packed_array;
+    alloc_ptr_pointer sparse;
+    alloc_pointer packed;
     size_type bucket;
     size_type count;
     entity_type free_list;