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

meta: reduce cost of meta prop

Michele Caini 1 год назад
Родитель
Сommit
da615cc8e0
4 измененных файлов с 131 добавлено и 15 удалено
  1. 9 3
      src/entt/meta/factory.hpp
  2. 16 6
      src/entt/meta/meta.hpp
  3. 24 5
      src/entt/meta/node.hpp
  4. 82 1
      src/entt/meta/range.hpp

+ 9 - 3
src/entt/meta/factory.hpp

@@ -111,13 +111,19 @@ protected:
     }
 
     void prop(meta_prop_node node) {
+        std::vector<meta_prop_node> *container = nullptr;
+
         if(bucket == parent) {
-            details->prop[node.id] = std::move(node);
+            container = &details->prop;
         } else if(invoke == nullptr) {
-            find_member(details->data)->prop[node.id] = std::move(node);
+            container = &find_member(details->data)->prop;
         } else {
-            find_overload()->prop[node.id] = std::move(node);
+            container = &find_overload()->prop;
         }
+
+        std::size_t pos{};
+        for(const std::size_t last = container->size(); (pos != last) && ((*container)[pos].id != node.id); ++pos) {}
+        (pos == container->size()) ? container->emplace_back(std::move(node)) : ((*container)[pos] = std::move(node));
     }
 
     void traits(const meta_traits value) {

+ 16 - 6
src/entt/meta/meta.hpp

@@ -948,8 +948,13 @@ struct meta_data {
      * @return The registered meta property for the given key, if any.
      */
     [[nodiscard]] meta_prop prop(const id_type key) const {
-        const auto it = node->prop.find(key);
-        return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{};
+        for(auto &&elem: node->prop) {
+            if(elem.id == key) {
+                return meta_prop{*ctx, elem};
+            }
+        }
+
+        return meta_prop{};
     }
 
     /**
@@ -1088,8 +1093,13 @@ struct meta_func {
      * @return The registered meta property for the given key, if any.
      */
     [[nodiscard]] meta_prop prop(const id_type key) const {
-        const auto it = node->prop.find(key);
-        return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{};
+        for(auto &&elem: node->prop) {
+            if(elem.id == key) {
+                return meta_prop{*ctx, elem};
+            }
+        }
+
+        return meta_prop{};
     }
 
     /*! @copydoc meta_data::traits */
@@ -1422,7 +1432,7 @@ public:
      * @return The registered meta data for the given identifier, if any.
      */
     [[nodiscard]] meta_data data(const id_type id) const {
-        const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), node, id);
+        const auto *elem = internal::deprecated_look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), node, id);
         return elem ? meta_data{*ctx, *elem} : meta_data{};
     }
 
@@ -1444,7 +1454,7 @@ public:
      * @return The registered meta function for the given identifier, if any.
      */
     [[nodiscard]] meta_func func(const id_type id) const {
-        const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node, id);
+        const auto *elem = internal::deprecated_look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node, id);
         return elem ? meta_func{*ctx, *elem} : meta_func{};
     }
 

+ 24 - 5
src/entt/meta/node.hpp

@@ -109,7 +109,7 @@ struct meta_data_node {
     bool (*set)(meta_handle, meta_any){};
     meta_any (*get)(const meta_ctx &, meta_handle){};
     meta_custom_node custom{};
-    dense_map<id_type, meta_prop_node, identity> prop{};
+    std::vector<meta_prop_node> prop{};
 };
 
 struct meta_func_node {
@@ -123,7 +123,7 @@ struct meta_func_node {
     meta_any (*invoke)(const meta_ctx &, meta_handle, meta_any *const){};
     std::shared_ptr<meta_func_node> next{};
     meta_custom_node custom{};
-    dense_map<id_type, meta_prop_node, identity> prop{};
+    std::vector<meta_prop_node> prop{};
 };
 
 struct meta_template_node {
@@ -140,7 +140,7 @@ struct meta_type_descriptor {
     std::vector<meta_conv_node> conv{};
     dense_map<id_type, meta_data_node, identity> data{};
     dense_map<id_type, meta_func_node, identity> func{};
-    dense_map<id_type, meta_prop_node, identity> prop{};
+    std::vector<meta_prop_node> prop{};
 };
 
 struct meta_type_node {
@@ -162,14 +162,14 @@ struct meta_type_node {
 };
 
 template<auto Member>
-auto *look_for(const meta_context &context, const meta_type_node &node, const id_type id) {
+auto *deprecated_look_for(const meta_context &context, const meta_type_node &node, const id_type id) {
     if(node.details) {
         if(const auto it = (node.details.get()->*Member).find(id); it != (node.details.get()->*Member).cend()) {
             return &it->second;
         }
 
         for(auto &&curr: node.details->base) {
-            if(auto *elem = look_for<Member>(context, curr.second.type(context), id); elem) {
+            if(auto *elem = deprecated_look_for<Member>(context, curr.second.type(context), id); elem) {
                 return elem;
             }
         }
@@ -178,6 +178,25 @@ auto *look_for(const meta_context &context, const meta_type_node &node, const id
     return static_cast<typename std::remove_reference_t<decltype(node.details.get()->*Member)>::mapped_type *>(nullptr);
 }
 
+template<auto Member>
+auto *look_for(const meta_context &context, const meta_type_node &node, const id_type id) {
+    if(node.details) {
+        for(auto &&elem: (node.details.get()->*Member)) {
+            if(elem.id == id) {
+                return &elem;
+            }
+        }
+
+        for(auto &&curr: node.details->base) {
+            if(auto *elem = look_for<Member>(context, curr.second.type(context), id); elem) {
+                return elem;
+            }
+        }
+    }
+
+    return static_cast<typename std::remove_reference_t<decltype(node.details.get()->*Member)>::value_type *>(nullptr);
+}
+
 template<typename Type>
 meta_type_node resolve(const meta_context &) noexcept;
 

+ 82 - 1
src/entt/meta/range.hpp

@@ -13,7 +13,7 @@ namespace entt {
 /*! @cond TURN_OFF_DOXYGEN */
 namespace internal {
 
-template<typename Type, typename It>
+template<typename Type, typename It, typename = void>
 struct meta_range_iterator final {
     using value_type = std::pair<id_type, Type>;
     using pointer = input_iterator_pointer<value_type>;
@@ -66,6 +66,87 @@ struct meta_range_iterator final {
         return (*this + -value);
     }
 
+    [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
+        return {it[value].id, Type{*ctx, it[value]}};
+    }
+
+    [[nodiscard]] constexpr pointer operator->() const noexcept {
+        return operator*();
+    }
+
+    [[nodiscard]] constexpr reference operator*() const noexcept {
+        return operator[](0);
+    }
+
+    template<typename... Args>
+    friend constexpr std::ptrdiff_t operator-(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept;
+
+    template<typename... Args>
+    friend constexpr bool operator==(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept;
+
+    template<typename... Args>
+    friend constexpr bool operator<(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept;
+
+private:
+    It it;
+    const meta_ctx *ctx;
+};
+
+template<typename Type, typename It>
+struct meta_range_iterator<Type, It, std::void_t<typename std::iterator_traits<It>::value_type::second_type>> final {
+    // deprecated work-in-progress specialization
+
+    using value_type = std::pair<id_type, Type>;
+    using pointer = input_iterator_pointer<value_type>;
+    using reference = value_type;
+    using difference_type = std::ptrdiff_t;
+    using iterator_category = std::input_iterator_tag;
+    using iterator_concept = std::random_access_iterator_tag;
+
+    constexpr meta_range_iterator() noexcept
+        : it{},
+          ctx{} {}
+
+    constexpr meta_range_iterator(const meta_ctx &area, const It iter) noexcept
+        : it{iter},
+          ctx{&area} {}
+
+    constexpr meta_range_iterator &operator++() noexcept {
+        return ++it, *this;
+    }
+
+    constexpr meta_range_iterator operator++(int) noexcept {
+        meta_range_iterator orig = *this;
+        return ++(*this), orig;
+    }
+
+    constexpr meta_range_iterator &operator--() noexcept {
+        return --it, *this;
+    }
+
+    constexpr meta_range_iterator operator--(int) noexcept {
+        meta_range_iterator orig = *this;
+        return operator--(), orig;
+    }
+
+    constexpr meta_range_iterator &operator+=(const difference_type value) noexcept {
+        it += value;
+        return *this;
+    }
+
+    constexpr meta_range_iterator operator+(const difference_type value) const noexcept {
+        meta_range_iterator copy = *this;
+        return (copy += value);
+    }
+
+    constexpr meta_range_iterator &operator-=(const difference_type value) noexcept {
+        return (*this += -value);
+    }
+
+    constexpr meta_range_iterator operator-(const difference_type value) const noexcept {
+        return (*this + -value);
+    }
+
     [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
         return {it[value].first, Type{*ctx, it[value].second}};
     }