Browse Source

sparse_set:
* added get_allocator
* internal review

Michele Caini 4 years ago
parent
commit
b5ec03f585
3 changed files with 36 additions and 19 deletions
  1. 1 0
      TODO
  2. 33 19
      src/entt/entity/sparse_set.hpp
  3. 2 0
      test/entt/entity/sparse_set.cpp

+ 1 - 0
TODO

@@ -10,6 +10,7 @@ WIP:
 * custom allocators all over
 * custom allocators all over
 
 
 WIP:
 WIP:
+* make sparse_set/storage adhere to AllocatorAwareContainer requriements
 * make value_type available from meta container types, otherwise we have to default construct a container to get it
 * make value_type available from meta container types, otherwise we have to default construct a container to get it
 * make it possible to register externally managed pools with the registry (allow for system centric mode)
 * make it possible to register externally managed pools with the registry (allow for system centric mode)
 * registry: switch to the udata/mixin model and get rid of poly storage, use pointer to sparse set only for pools, discard pool_data type.
 * registry: switch to the udata/mixin model and get rid of poly storage, use pointer to sparse set only for pools, discard pool_data type.

+ 33 - 19
src/entt/entity/sparse_set.hpp

@@ -54,17 +54,24 @@ class basic_sparse_set {
     static constexpr auto growth_factor = 1.5;
     static constexpr auto growth_factor = 1.5;
     static constexpr auto sparse_page = ENTT_SPARSE_PAGE;
     static constexpr auto sparse_page = ENTT_SPARSE_PAGE;
 
 
-    using entity_traits = entt_traits<Entity>;
+    using allocator_traits = std::allocator_traits<Allocator>;
 
 
-    using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Entity>;
-    using alloc_pointer = typename alloc_traits::pointer;
+    using alloc = typename allocator_traits::template rebind_alloc<Entity>;
+    using alloc_traits = typename std::allocator_traits<alloc>;
     using alloc_const_pointer = typename alloc_traits::const_pointer;
     using alloc_const_pointer = typename alloc_traits::const_pointer;
+    using alloc_pointer = typename alloc_traits::pointer;
 
 
-    using bucket_alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<alloc_pointer>;
-    using bucket_alloc_pointer = typename bucket_alloc_traits::pointer;
+    using alloc_ptr = typename allocator_traits::template rebind_alloc<alloc_pointer>;
+    using alloc_ptr_traits = typename std::allocator_traits<alloc_ptr>;
+    using alloc_ptr_pointer = typename alloc_ptr_traits::pointer;
+
+    // TODO using bucket_alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<alloc_pointer>;
+    // TODO using bucket_alloc_pointer = typename bucket_alloc_traits::pointer;
+
+    using entity_traits = entt_traits<Entity>;
 
 
     static_assert(alloc_traits::propagate_on_container_move_assignment::value);
     static_assert(alloc_traits::propagate_on_container_move_assignment::value);
-    static_assert(bucket_alloc_traits::propagate_on_container_move_assignment::value);
+    static_assert(alloc_ptr_traits::propagate_on_container_move_assignment::value);
 
 
     struct sparse_set_iterator final {
     struct sparse_set_iterator final {
         using difference_type = typename entity_traits::difference_type;
         using difference_type = typename entity_traits::difference_type;
@@ -174,13 +181,14 @@ class basic_sparse_set {
     [[nodiscard]] auto assure_page(const std::size_t idx) {
     [[nodiscard]] auto assure_page(const std::size_t idx) {
         if(!(idx < bucket)) {
         if(!(idx < bucket)) {
             const size_type sz = idx + 1u;
             const size_type sz = idx + 1u;
-            const auto mem = bucket_alloc_traits::allocate(bucket_allocator, sz);
+            alloc_ptr allocator_ptr{allocator};
+            const auto mem = alloc_ptr_traits::allocate(allocator_ptr, sz);
 
 
             std::uninitialized_value_construct(mem + bucket, mem + sz);
             std::uninitialized_value_construct(mem + bucket, mem + sz);
             std::uninitialized_copy(sparse, sparse + bucket, mem);
             std::uninitialized_copy(sparse, sparse + bucket, mem);
 
 
             std::destroy(sparse, sparse + bucket);
             std::destroy(sparse, sparse + bucket);
-            bucket_alloc_traits::deallocate(bucket_allocator, sparse, bucket);
+            alloc_ptr_traits::deallocate(allocator_ptr, sparse, bucket);
 
 
             sparse = mem;
             sparse = mem;
             bucket = sz;
             bucket = sz;
@@ -219,8 +227,10 @@ class basic_sparse_set {
 
 
             std::destroy(packed, packed + reserved);
             std::destroy(packed, packed + reserved);
             std::destroy(sparse, sparse + bucket);
             std::destroy(sparse, sparse + bucket);
+
+            alloc_ptr allocator_ptr{allocator};
             alloc_traits::deallocate(allocator, packed, reserved);
             alloc_traits::deallocate(allocator, packed, reserved);
-            bucket_alloc_traits::deallocate(bucket_allocator, sparse, bucket);
+            alloc_ptr_traits::deallocate(allocator_ptr, sparse, bucket);
         }
         }
     }
     }
 
 
@@ -275,7 +285,7 @@ protected:
 
 
 public:
 public:
     /*! @brief Allocator type. */
     /*! @brief Allocator type. */
-    using allocator_type = typename alloc_traits::allocator_type;
+    using allocator_type = Allocator;
     /*! @brief Underlying entity identifier. */
     /*! @brief Underlying entity identifier. */
     using entity_type = Entity;
     using entity_type = Entity;
     /*! @brief Unsigned integer type. */
     /*! @brief Unsigned integer type. */
@@ -294,8 +304,7 @@ public:
      */
      */
     explicit basic_sparse_set(deletion_policy pol, const allocator_type &alloc = {})
     explicit basic_sparse_set(deletion_policy pol, const allocator_type &alloc = {})
         : allocator{alloc},
         : allocator{alloc},
-          bucket_allocator{alloc},
-          sparse{bucket_alloc_traits::allocate(bucket_allocator, 0u)},
+          sparse{alloc_ptr_traits::allocate(alloc_ptr{allocator}, 0u)},
           packed{alloc_traits::allocate(allocator, 0u)},
           packed{alloc_traits::allocate(allocator, 0u)},
           bucket{0u},
           bucket{0u},
           count{0u},
           count{0u},
@@ -318,8 +327,7 @@ public:
      */
      */
     basic_sparse_set(basic_sparse_set &&other) ENTT_NOEXCEPT
     basic_sparse_set(basic_sparse_set &&other) ENTT_NOEXCEPT
         : allocator{std::move(other.allocator)},
         : allocator{std::move(other.allocator)},
-          bucket_allocator{std::move(other.bucket_allocator)},
-          sparse{std::exchange(other.sparse, bucket_alloc_pointer{})},
+          sparse{std::exchange(other.sparse, alloc_ptr_pointer{})},
           packed{std::exchange(other.packed, alloc_pointer{})},
           packed{std::exchange(other.packed, alloc_pointer{})},
           bucket{std::exchange(other.bucket, 0u)},
           bucket{std::exchange(other.bucket, 0u)},
           count{std::exchange(other.count, 0u)},
           count{std::exchange(other.count, 0u)},
@@ -342,8 +350,7 @@ public:
         release_memory();
         release_memory();
 
 
         allocator = std::move(other.allocator);
         allocator = std::move(other.allocator);
-        bucket_allocator = std::move(other.bucket_allocator);
-        sparse = std::exchange(other.sparse, bucket_alloc_pointer{});
+        sparse = std::exchange(other.sparse, alloc_ptr_pointer{});
         packed = std::exchange(other.packed, alloc_pointer{});
         packed = std::exchange(other.packed, alloc_pointer{});
         bucket = std::exchange(other.bucket, 0u);
         bucket = std::exchange(other.bucket, 0u);
         count = std::exchange(other.count, 0u);
         count = std::exchange(other.count, 0u);
@@ -354,6 +361,14 @@ public:
         return *this;
         return *this;
     }
     }
 
 
+    /**
+     * @brief Returns the associated allocator.
+     * @return The associated allocator.
+     */
+    [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
+        return allocator_type{allocator};
+    }
+
     /**
     /**
      * @brief Returns the deletion policy of a sparse set.
      * @brief Returns the deletion policy of a sparse set.
      * @return The deletion policy of the sparse set.
      * @return The deletion policy of the sparse set.
@@ -852,9 +867,8 @@ public:
     }
     }
 
 
 private:
 private:
-    typename alloc_traits::allocator_type allocator;
-    typename bucket_alloc_traits::allocator_type bucket_allocator;
-    bucket_alloc_pointer sparse;
+    alloc allocator;
+    alloc_ptr_pointer sparse;
     alloc_pointer packed;
     alloc_pointer packed;
     std::size_t bucket;
     std::size_t bucket;
     std::size_t count;
     std::size_t count;

+ 2 - 0
test/entt/entity/sparse_set.cpp

@@ -16,6 +16,8 @@ struct boxed_int { int value; };
 TEST(SparseSet, Functionalities) {
 TEST(SparseSet, Functionalities) {
     entt::sparse_set set;
     entt::sparse_set set;
 
 
+    ASSERT_NO_THROW(auto alloc = set.get_allocator());
+
     set.reserve(42);
     set.reserve(42);
 
 
     ASSERT_EQ(set.capacity(), 42u);
     ASSERT_EQ(set.capacity(), 42u);