Kaynağa Gözat

sparse_set/storage: no zero sized allocations on construction

Michele Caini 4 yıl önce
ebeveyn
işleme
516a9209b7
2 değiştirilmiş dosya ile 37 ekleme ve 35 silme
  1. 21 17
      src/entt/entity/sparse_set.hpp
  2. 16 18
      src/entt/entity/storage.hpp

+ 21 - 17
src/entt/entity/sparse_set.hpp

@@ -183,10 +183,12 @@ class basic_sparse_set {
             const auto mem = alloc_ptr_traits::allocate(allocator_ptr, sz);
             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::destroy(sparse, sparse + bucket);
-            alloc_ptr_traits::deallocate(allocator_ptr, sparse, bucket);
+            if(sparse) {
+                std::uninitialized_copy(sparse, sparse + bucket, mem);
+                std::destroy(sparse, sparse + bucket);
+                alloc_ptr_traits::deallocate(allocator_ptr, sparse, bucket);
+            }
 
 
             sparse = mem;
             sparse = mem;
             bucket = sz;
             bucket = sz;
@@ -205,32 +207,38 @@ class basic_sparse_set {
         ENTT_ASSERT((req != len) && !(req < count), "Invalid request");
         ENTT_ASSERT((req != len) && !(req < count), "Invalid request");
         const auto mem = alloc_traits::allocate(allocator, req);
         const auto mem = alloc_traits::allocate(allocator, req);
 
 
-        std::uninitialized_copy(packed, packed + count, mem);
         std::uninitialized_fill(mem + count, mem + req, tombstone);
         std::uninitialized_fill(mem + count, mem + req, tombstone);
 
 
-        std::destroy(packed, packed + len);
-        alloc_traits::deallocate(allocator, packed, len);
+        if(packed) {
+            std::uninitialized_copy(packed, packed + count, mem);
+            std::destroy(packed, packed + len);
+            alloc_traits::deallocate(allocator, packed, len);
+        }
 
 
         packed = mem;
         packed = mem;
         len = req;
         len = req;
     }
     }
 
 
     void release_memory() {
     void release_memory() {
+        auto &&[allocator, len] = reserved;
+
         if(packed) {
         if(packed) {
-            auto &&[allocator, len] = reserved;
+            std::destroy(packed, packed + len);
+            alloc_traits::deallocate(allocator, packed, len);
+        }
+
+        if(sparse) {
+            alloc_ptr allocator_ptr{allocator};
 
 
             for(size_type pos{}; pos < bucket; ++pos) {
             for(size_type pos{}; pos < bucket; ++pos) {
                 if(sparse[pos]) {
                 if(sparse[pos]) {
                     std::destroy(sparse[pos], sparse[pos] + sparse_page);
                     std::destroy(sparse[pos], sparse[pos] + sparse_page);
                     alloc_traits::deallocate(allocator, sparse[pos], sparse_page);
                     alloc_traits::deallocate(allocator, sparse[pos], sparse_page);
                 }
                 }
-            }
 
 
-            std::destroy(packed, packed + len);
-            std::destroy(sparse, sparse + bucket);
+                alloc_ptr_traits::destroy(allocator_ptr, std::addressof(sparse[pos]));
+            }
 
 
-            alloc_ptr allocator_ptr{allocator};
-            alloc_traits::deallocate(allocator, packed, len);
             alloc_ptr_traits::deallocate(allocator_ptr, sparse, bucket);
             alloc_ptr_traits::deallocate(allocator_ptr, sparse, bucket);
         }
         }
     }
     }
@@ -311,11 +319,7 @@ public:
           count{0u},
           count{0u},
           free_list{tombstone},
           free_list{tombstone},
           mode{pol}
           mode{pol}
-    {
-        alloc_ptr allocator_ptr{reserved.first()};
-        sparse = alloc_ptr_traits::allocate(allocator_ptr, 0u);
-        packed = alloc_traits::allocate(reserved.first(), 0u);
-    }
+    {}
 
 
     /**
     /**
      * @brief Constructs an empty container with the given allocator.
      * @brief Constructs an empty container with the given allocator.

+ 16 - 18
src/entt/entity/storage.hpp

@@ -180,12 +180,12 @@ class basic_storage_impl: public basic_sparse_set<Entity, typename std::allocato
 
 
     void release_memory() {
     void release_memory() {
         if(packed) {
         if(packed) {
-            auto &&[allocator, len] = bucket;
-            alloc_ptr allocator_ptr{allocator};
-
             // no-throw stable erase iteration
             // no-throw stable erase iteration
             underlying_type::clear();
             underlying_type::clear();
 
 
+            auto &&[allocator, len] = bucket;
+            alloc_ptr allocator_ptr{allocator};
+
             for(size_type pos{}; pos < len; ++pos) {
             for(size_type pos{}; pos < len; ++pos) {
                 alloc_traits::deallocate(allocator, packed[pos], packed_page);
                 alloc_traits::deallocate(allocator, packed[pos], packed_page);
                 alloc_ptr_traits::destroy(allocator_ptr, std::addressof(packed[pos]));
                 alloc_ptr_traits::destroy(allocator_ptr, std::addressof(packed[pos]));
@@ -202,26 +202,27 @@ class basic_storage_impl: public basic_sparse_set<Entity, typename std::allocato
 
 
             const size_type sz = idx + 1u;
             const size_type sz = idx + 1u;
             const auto mem = alloc_ptr_traits::allocate(allocator_ptr, sz);
             const auto mem = alloc_ptr_traits::allocate(allocator_ptr, sz);
-            std::uninitialized_copy(packed, packed + len, mem);
-            size_type pos{};
+            std::uninitialized_value_construct(mem + len, mem + sz);
 
 
             ENTT_TRY {
             ENTT_TRY {
-                for(pos = len; pos < sz; ++pos) {
-                    auto pg = alloc_traits::allocate(allocator, packed_page);
-                    alloc_ptr_traits::construct(allocator_ptr, std::addressof(mem[pos]), pg);
+                for(auto pos = len; pos < sz; ++pos) {
+                    mem[pos] = alloc_traits::allocate(allocator, packed_page);
                 }
                 }
             } ENTT_CATCH {
             } ENTT_CATCH {
-                for(auto next = len; next < pos; ++next) {
-                    alloc_traits::deallocate(allocator, mem[next], packed_page);
+                for(auto pos = len; pos < sz && mem[pos]; ++pos) {
+                    alloc_traits::deallocate(allocator, mem[pos], packed_page);
                 }
                 }
 
 
-                std::destroy(mem, mem + pos);
+                std::destroy(mem + len, mem + sz);
                 alloc_ptr_traits::deallocate(allocator_ptr, mem, sz);
                 alloc_ptr_traits::deallocate(allocator_ptr, mem, sz);
                 ENTT_THROW;
                 ENTT_THROW;
             }
             }
 
 
-            std::destroy(packed, packed + len);
-            alloc_ptr_traits::deallocate(allocator_ptr, packed, len);
+            if(packed) {
+                std::uninitialized_copy(packed, packed + len, mem);
+                std::destroy(packed, packed + len);
+                alloc_ptr_traits::deallocate(allocator_ptr, packed, len);
+            }
 
 
             packed = mem;
             packed = mem;
             len = sz;
             len = sz;
@@ -238,9 +239,9 @@ class basic_storage_impl: public basic_sparse_set<Entity, typename std::allocato
 
 
             for(auto pos = length; pos < len; ++pos) {
             for(auto pos = length; pos < len; ++pos) {
                 alloc_traits::deallocate(allocator, packed[pos], packed_page);
                 alloc_traits::deallocate(allocator, packed[pos], packed_page);
-                alloc_ptr_traits::destroy(allocator_ptr, std::addressof(packed[pos]));
             }
             }
 
 
+            std::destroy(packed, packed + len);
             alloc_ptr_traits::deallocate(allocator_ptr, packed, len);
             alloc_ptr_traits::deallocate(allocator_ptr, packed, len);
 
 
             packed = mem;
             packed = mem;
@@ -331,10 +332,7 @@ public:
         : underlying_type{deletion_policy{comp_traits::in_place_delete::value}, allocator},
         : underlying_type{deletion_policy{comp_traits::in_place_delete::value}, allocator},
           bucket{allocator, 0u},
           bucket{allocator, 0u},
           packed{}
           packed{}
-    {
-        alloc_ptr allocator_ptr{bucket.first()};
-        packed = alloc_ptr_traits::allocate(allocator_ptr, 0u);
-    }
+    {}
 
 
     /**
     /**
      * @brief Move constructor.
      * @brief Move constructor.