Просмотр исходного кода

sparse_set: non-copyable allocator-aware container

Michele Caini 4 лет назад
Родитель
Сommit
ef8211a46e
2 измененных файлов с 9 добавлено и 17 удалено
  1. 2 2
      TODO
  2. 7 15
      src/entt/entity/sparse_set.hpp

+ 2 - 2
TODO

@@ -5,13 +5,13 @@
 * custom pools example (multi instance, tables, enable/disable, and so on...)
 
 WIP:
-* make sparse_set/storage adhere to AllocatorAwareContainer requirements
+* make storage adhere to AllocatorAwareContainer requirements
 * fast-contains for sparse sets (low prio but nice-to-have)
 * runtime components (registry), runtime events (dispatcher/emitter), ...
 * runtime_view/registry, remove reference to basic_sparse_set<E>
 * make pools available (registry/view/group), review operator| for views, make views accept registry to ctor
 * make view.lead() or similar available to return leading pool (useful for mt)
-* dedicated entity storage, in-place O(1) release/destroy for non-orphaned entities
+* dedicated entity storage, in-place O(1) release/destroy for non-orphaned entities, out-of-sync model
 * non-throwing sparse set emplace (see previous line)
 * custom allocators all over
 

+ 7 - 15
src/entt/entity/sparse_set.hpp

@@ -10,7 +10,7 @@
 #include "../config/config.h"
 #include "../core/algorithm.hpp"
 #include "../core/compressed_pair.hpp"
-#include "../core/fwd.hpp"
+#include "../core/memory.hpp"
 #include "entity.hpp"
 #include "fwd.hpp"
 
@@ -68,8 +68,6 @@ class basic_sparse_set {
 
     using entity_traits = entt_traits<Entity>;
 
-    static_assert(alloc_traits::is_always_equal::value, "Unequal allocators not supported");
-
     struct sparse_set_iterator final {
         using difference_type = typename entity_traits::difference_type;
         using value_type = Entity;
@@ -353,7 +351,9 @@ public:
           count{std::exchange(other.count, size_type{})},
           free_list{std::exchange(other.free_list, tombstone)},
           mode{other.mode}
-    {}
+    {
+        ENTT_ASSERT(alloc_traits::is_always_equal{} || reserved.first() == other.reserved.first(), "Copying a sparse set is not allowed");
+    }
 
     /*! @brief Default destructor. */
     virtual ~basic_sparse_set() {
@@ -367,11 +367,8 @@ public:
      */
     basic_sparse_set & operator=(basic_sparse_set &&other) ENTT_NOEXCEPT {
         release_memory();
-
-        if constexpr(alloc_traits::propagate_on_container_move_assignment::value) {
-            reserved.first() = std::move(other.reserved.first());
-        }
-
+        propagate_on_container_move_assignment(reserved.first(), other.reserved.first());
+        ENTT_ASSERT(alloc_traits::is_always_equal{} || 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{});
@@ -379,7 +376,6 @@ public:
         count = std::exchange(other.count, size_type{});
         free_list = std::exchange(other.free_list, tombstone);
         mode = other.mode;
-
         return *this;
     }
 
@@ -389,11 +385,7 @@ public:
      */
     void swap(basic_sparse_set &other) {
         using std::swap;
-
-        if constexpr(alloc_traits::propagate_on_container_swap::value) {
-            swap(reserved.first(), other.reserved.first());
-        }
-
+        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);