Michele Caini 5 лет назад
Родитель
Сommit
8db61a38cc
1 измененных файлов с 64 добавлено и 60 удалено
  1. 64 60
      src/entt/entity/sparse_set.hpp

+ 64 - 60
src/entt/entity/sparse_set.hpp

@@ -2,7 +2,6 @@
 #define ENTT_ENTITY_SPARSE_SET_HPP
 #define ENTT_ENTITY_SPARSE_SET_HPP
 
 
 
 
-#include <algorithm>
 #include <iterator>
 #include <iterator>
 #include <utility>
 #include <utility>
 #include <vector>
 #include <vector>
@@ -47,19 +46,20 @@ namespace entt {
  */
  */
 template<typename Entity>
 template<typename Entity>
 class sparse_set {
 class sparse_set {
-    using traits_type = entt_traits<std::underlying_type_t<Entity>>;
-
     static_assert(ENTT_PAGE_SIZE && ((ENTT_PAGE_SIZE & (ENTT_PAGE_SIZE - 1)) == 0));
     static_assert(ENTT_PAGE_SIZE && ((ENTT_PAGE_SIZE & (ENTT_PAGE_SIZE - 1)) == 0));
-    static constexpr auto entt_per_page = ENTT_PAGE_SIZE / sizeof(typename traits_type::entity_type);
+    static constexpr auto entt_per_page = ENTT_PAGE_SIZE / sizeof(Entity);
+
+    using traits_type = entt_traits<std::underlying_type_t<Entity>>;
+    using page_type = std::unique_ptr<Entity[]>;
 
 
     class sparse_set_iterator final {
     class sparse_set_iterator final {
         friend class sparse_set<Entity>;
         friend class sparse_set<Entity>;
 
 
-        using direct_type = std::vector<Entity>;
+        using packed_type = std::vector<Entity>;
         using index_type = typename traits_type::difference_type;
         using index_type = typename traits_type::difference_type;
 
 
-        sparse_set_iterator(const direct_type &ref, const index_type idx) ENTT_NOEXCEPT
-            : direct{&ref}, index{idx}
+        sparse_set_iterator(const packed_type &ref, const index_type idx) ENTT_NOEXCEPT
+            : packed{&ref}, index{idx}
         {}
         {}
 
 
     public:
     public:
@@ -113,7 +113,7 @@ class sparse_set {
 
 
         reference operator[](const difference_type value) const {
         reference operator[](const difference_type value) const {
             const auto pos = size_type(index-value-1);
             const auto pos = size_type(index-value-1);
-            return (*direct)[pos];
+            return (*packed)[pos];
         }
         }
 
 
         bool operator==(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
         bool operator==(const sparse_set_iterator &other) const ENTT_NOEXCEPT {
@@ -142,7 +142,7 @@ class sparse_set {
 
 
         pointer operator->() const {
         pointer operator->() const {
             const auto pos = size_type(index-1);
             const auto pos = size_type(index-1);
-            return &(*direct)[pos];
+            return &(*packed)[pos];
         }
         }
 
 
         reference operator*() const {
         reference operator*() const {
@@ -150,7 +150,7 @@ class sparse_set {
         }
         }
 
 
     private:
     private:
-        const direct_type *direct;
+        const packed_type *packed;
         index_type index;
         index_type index;
     };
     };
 
 
@@ -162,18 +162,20 @@ class sparse_set {
         return std::size_t{to_integral(entt) & (entt_per_page - 1)};
         return std::size_t{to_integral(entt) & (entt_per_page - 1)};
     }
     }
 
 
-    Entity * assure(const std::size_t pos) {
-        if(!(pos < reverse.size())) {
-            reverse.resize(pos+1);
+    page_type & assure(const std::size_t pos) {
+        if(!(pos < sparse.size())) {
+            sparse.resize(pos+1);
         }
         }
 
 
-        if(!reverse[pos]) {
-            reverse[pos] = std::make_unique<entity_type[]>(entt_per_page);
+        if(!sparse[pos]) {
+            sparse[pos] = std::make_unique<entity_type[]>(entt_per_page);
             // null is safe in all cases for our purposes
             // null is safe in all cases for our purposes
-            std::fill_n(reverse[pos].get(), entt_per_page, null);
+            for(auto *first = sparse[pos].get(), *last = first + entt_per_page; first != last; ++first) {
+                *first = null;
+            }
         }
         }
 
 
-        return reverse[pos].get();
+        return sparse[pos];
     }
     }
 
 
 public:
 public:
@@ -205,7 +207,7 @@ public:
      * @param cap Desired capacity.
      * @param cap Desired capacity.
      */
      */
     void reserve(const size_type cap) {
     void reserve(const size_type cap) {
-        direct.reserve(cap);
+        packed.reserve(cap);
     }
     }
 
 
     /**
     /**
@@ -214,18 +216,18 @@ public:
      * @return Capacity of the sparse set.
      * @return Capacity of the sparse set.
      */
      */
     size_type capacity() const ENTT_NOEXCEPT {
     size_type capacity() const ENTT_NOEXCEPT {
-        return direct.capacity();
+        return packed.capacity();
     }
     }
 
 
     /*! @brief Requests the removal of unused capacity. */
     /*! @brief Requests the removal of unused capacity. */
     void shrink_to_fit() {
     void shrink_to_fit() {
         // conservative approach
         // conservative approach
-        if(direct.empty()) {
-            reverse.clear();
+        if(packed.empty()) {
+            sparse.clear();
         }
         }
 
 
-        reverse.shrink_to_fit();
-        direct.shrink_to_fit();
+        sparse.shrink_to_fit();
+        packed.shrink_to_fit();
     }
     }
 
 
     /**
     /**
@@ -239,7 +241,7 @@ public:
      * @return Extent of the sparse set.
      * @return Extent of the sparse set.
      */
      */
     size_type extent() const ENTT_NOEXCEPT {
     size_type extent() const ENTT_NOEXCEPT {
-        return reverse.size() * entt_per_page;
+        return sparse.size() * entt_per_page;
     }
     }
 
 
     /**
     /**
@@ -253,7 +255,7 @@ public:
      * @return Number of elements.
      * @return Number of elements.
      */
      */
     size_type size() const ENTT_NOEXCEPT {
     size_type size() const ENTT_NOEXCEPT {
-        return direct.size();
+        return packed.size();
     }
     }
 
 
     /**
     /**
@@ -261,7 +263,7 @@ public:
      * @return True if the sparse set is empty, false otherwise.
      * @return True if the sparse set is empty, false otherwise.
      */
      */
     bool empty() const ENTT_NOEXCEPT {
     bool empty() const ENTT_NOEXCEPT {
-        return direct.empty();
+        return packed.empty();
     }
     }
 
 
     /**
     /**
@@ -280,7 +282,7 @@ public:
      * @return A pointer to the internal packed array.
      * @return A pointer to the internal packed array.
      */
      */
     const entity_type * data() const ENTT_NOEXCEPT {
     const entity_type * data() const ENTT_NOEXCEPT {
-        return direct.data();
+        return packed.data();
     }
     }
 
 
     /**
     /**
@@ -297,8 +299,8 @@ public:
      * @return An iterator to the first entity of the internal packed array.
      * @return An iterator to the first entity of the internal packed array.
      */
      */
     iterator begin() const ENTT_NOEXCEPT {
     iterator begin() const ENTT_NOEXCEPT {
-        const typename traits_type::difference_type pos = direct.size();
-        return iterator{direct, pos};
+        const typename traits_type::difference_type pos = packed.size();
+        return iterator{packed, pos};
     }
     }
 
 
     /**
     /**
@@ -316,7 +318,7 @@ public:
      * internal packed array.
      * internal packed array.
      */
      */
     iterator end() const ENTT_NOEXCEPT {
     iterator end() const ENTT_NOEXCEPT {
-        return iterator{direct, {}};
+        return iterator{packed, {}};
     }
     }
 
 
     /**
     /**
@@ -336,8 +338,8 @@ public:
      */
      */
     bool contains(const entity_type entt) const {
     bool contains(const entity_type entt) const {
         const auto curr = page(entt);
         const auto curr = page(entt);
-        // testing against null permits to avoid accessing the direct vector
-        return (curr < reverse.size() && reverse[curr] && reverse[curr][offset(entt)] != null);
+        // testing against null permits to avoid accessing the packed array
+        return (curr < sparse.size() && sparse[curr] && sparse[curr][offset(entt)] != null);
     }
     }
 
 
     /*! @copydoc contains */
     /*! @copydoc contains */
@@ -360,7 +362,7 @@ public:
      */
      */
     size_type index(const entity_type entt) const {
     size_type index(const entity_type entt) const {
         ENTT_ASSERT(contains(entt));
         ENTT_ASSERT(contains(entt));
-        return size_type(reverse[page(entt)][offset(entt)]);
+        return size_type(sparse[page(entt)][offset(entt)]);
     }
     }
 
 
     /**
     /**
@@ -376,8 +378,8 @@ public:
      */
      */
     void emplace(const entity_type entt) {
     void emplace(const entity_type entt) {
         ENTT_ASSERT(!contains(entt));
         ENTT_ASSERT(!contains(entt));
-        assure(page(entt))[offset(entt)] = entity_type(direct.size());
-        direct.push_back(entt);
+        assure(page(entt))[offset(entt)] = entity_type(packed.size());
+        packed.push_back(entt);
     }
     }
 
 
     /*! @copydoc emplace */
     /*! @copydoc emplace */
@@ -401,12 +403,14 @@ public:
      */
      */
     template<typename It>
     template<typename It>
     void insert(It first, It last) {
     void insert(It first, It last) {
-        std::for_each(first, last, [this, next = direct.size()](const auto entt) mutable {
+        auto next = packed.size();
+        packed.insert(packed.end(), first, last);
+
+        while(first != last) {
+            const auto entt = *(first++);
             ENTT_ASSERT(!contains(entt));
             ENTT_ASSERT(!contains(entt));
             assure(page(entt))[offset(entt)] = entity_type(next++);
             assure(page(entt))[offset(entt)] = entity_type(next++);
-        });
-
-        direct.insert(direct.end(), first, last);
+        }
     }
     }
 
 
     /*! @copydoc insert */
     /*! @copydoc insert */
@@ -431,10 +435,10 @@ public:
         ENTT_ASSERT(contains(entt));
         ENTT_ASSERT(contains(entt));
         const auto curr = page(entt);
         const auto curr = page(entt);
         const auto pos = offset(entt);
         const auto pos = offset(entt);
-        direct[size_type(reverse[curr][pos])] = entity_type(direct.back());
-        reverse[page(direct.back())][offset(direct.back())] = reverse[curr][pos];
-        reverse[curr][pos] = null;
-        direct.pop_back();
+        packed[size_type(sparse[curr][pos])] = entity_type(packed.back());
+        sparse[page(packed.back())][offset(packed.back())] = sparse[curr][pos];
+        sparse[curr][pos] = null;
+        packed.pop_back();
     }
     }
 
 
     /*! @copydoc erase */
     /*! @copydoc erase */
@@ -459,9 +463,9 @@ public:
      * @param rhs A valid entity identifier.
      * @param rhs A valid entity identifier.
      */
      */
     virtual void swap(const entity_type lhs, const entity_type rhs) {
     virtual void swap(const entity_type lhs, const entity_type rhs) {
-        auto &from = reverse[page(lhs)][offset(lhs)];
-        auto &to = reverse[page(rhs)][offset(rhs)];
-        std::swap(direct[size_type(from)], direct[size_type(to)]);
+        auto &from = sparse[page(lhs)][offset(lhs)];
+        auto &to = sparse[page(rhs)][offset(rhs)];
+        std::swap(packed[size_type(from)], packed[size_type(to)]);
         std::swap(from, to);
         std::swap(from, to);
     }
     }
 
 
@@ -511,13 +515,13 @@ public:
 
 
         const auto length = std::distance(first, last);
         const auto length = std::distance(first, last);
         const auto skip = std::distance(last, end());
         const auto skip = std::distance(last, end());
-        const auto to = direct.rend() - skip;
+        const auto to = packed.rend() - skip;
         const auto from = to - length;
         const auto from = to - length;
 
 
         algo(from, to, std::move(compare), std::forward<Args>(args)...);
         algo(from, to, std::move(compare), std::forward<Args>(args)...);
 
 
         for(size_type pos = skip, end = skip+length; pos < end; ++pos) {
         for(size_type pos = skip, end = skip+length; pos < end; ++pos) {
-            reverse[page(direct[pos])][offset(direct[pos])] = entity_type(pos);
+            sparse[page(packed[pos])][offset(packed[pos])] = entity_type(pos);
         }
         }
     }
     }
 
 
@@ -555,21 +559,21 @@ public:
 
 
         const auto length = std::distance(first, last);
         const auto length = std::distance(first, last);
         const auto skip = std::distance(last, end());
         const auto skip = std::distance(last, end());
-        const auto to = direct.rend() - skip;
+        const auto to = packed.rend() - skip;
         const auto from = to - length;
         const auto from = to - length;
 
 
         algo(from, to, std::move(compare), std::forward<Args>(args)...);
         algo(from, to, std::move(compare), std::forward<Args>(args)...);
 
 
         for(size_type pos = skip, end = skip+length; pos < end; ++pos) {
         for(size_type pos = skip, end = skip+length; pos < end; ++pos) {
             auto curr = pos;
             auto curr = pos;
-            auto next = index(direct[curr]);
+            auto next = index(packed[curr]);
 
 
             while(curr != next) {
             while(curr != next) {
-                apply(direct[curr], direct[next]);
-                reverse[page(direct[curr])][offset(direct[curr])] = entity_type(curr);
+                apply(packed[curr], packed[next]);
+                sparse[page(packed[curr])][offset(packed[curr])] = entity_type(curr);
 
 
                 curr = next;
                 curr = next;
-                next = index(direct[curr]);
+                next = index(packed[curr]);
             }
             }
         }
         }
     }
     }
@@ -598,12 +602,12 @@ public:
         const auto to = other.end();
         const auto to = other.end();
         auto from = other.begin();
         auto from = other.begin();
 
 
-        size_type pos = direct.size() - 1;
+        size_type pos = packed.size() - 1;
 
 
         while(pos && from != to) {
         while(pos && from != to) {
             if(contains(*from)) {
             if(contains(*from)) {
-                if(*from != direct[pos]) {
-                    swap(direct[pos], *from);
+                if(*from != packed[pos]) {
+                    swap(packed[pos], *from);
                 }
                 }
 
 
                 --pos;
                 --pos;
@@ -617,13 +621,13 @@ public:
      * @brief Clears a sparse set.
      * @brief Clears a sparse set.
      */
      */
     void clear() ENTT_NOEXCEPT {
     void clear() ENTT_NOEXCEPT {
-        reverse.clear();
-        direct.clear();
+        sparse.clear();
+        packed.clear();
     }
     }
 
 
 private:
 private:
-    std::vector<std::unique_ptr<entity_type[]>> reverse;
-    std::vector<entity_type> direct;
+    std::vector<page_type> sparse;
+    std::vector<entity_type> packed;
 };
 };