Browse Source

meta: static local meta type node fallback

skypjack 6 months ago
parent
commit
e9b3eee6d3
3 changed files with 49 additions and 42 deletions
  1. 29 23
      src/entt/meta/factory.hpp
  2. 6 6
      src/entt/meta/meta.hpp
  3. 14 13
      src/entt/meta/node.hpp

+ 29 - 23
src/entt/meta/factory.hpp

@@ -32,14 +32,18 @@ namespace internal {
 class basic_meta_factory {
     using invoke_type = std::remove_pointer_t<decltype(meta_func_node::invoke)>;
 
+    auto &fetch_node() noexcept {
+        return meta_context::from(*ctx).value[parent];
+    }
+
     auto *find_member_or_assert() {
-        auto *member = find_member<&meta_data_node::id>(details->data, bucket);
+        auto *member = find_member<&meta_data_node::id>(fetch_node().details->data, bucket);
         ENTT_ASSERT(member != nullptr, "Cannot find member");
         return member;
     }
 
     auto *find_overload_or_assert() {
-        auto *overload = find_overload(find_member<&meta_func_node::id>(details->func, bucket), invoke);
+        auto *overload = find_overload(find_member<&meta_func_node::id>(fetch_node().details->func, bucket), invoke);
         ENTT_ASSERT(overload != nullptr, "Cannot find overload");
         return overload;
     }
@@ -52,7 +56,7 @@ class basic_meta_factory {
 protected:
     void type(const id_type id, const char *name) noexcept {
         reset_bucket(parent);
-        auto &&elem = meta_context::from(*ctx).value[parent];
+        auto &elem = fetch_node();
         ENTT_ASSERT(elem.id == id || !resolve(*ctx, id), "Duplicate identifier");
         elem.name = name;
         elem.id = id;
@@ -60,36 +64,42 @@ protected:
 
     template<typename Type>
     void insert_or_assign(Type node) {
+        auto &elem = fetch_node();
+
         reset_bucket(parent);
 
         if constexpr(std::is_same_v<Type, meta_base_node>) {
-            auto *member = find_member<&meta_base_node::type>(details->base, node.type);
-            member ? (*member = node) : details->base.emplace_back(node);
+            auto *member = find_member<&meta_base_node::type>(elem.details->base, node.type);
+            member ? (*member = node) : elem.details->base.emplace_back(node);
         } else if constexpr(std::is_same_v<Type, meta_conv_node>) {
-            auto *member = find_member<&meta_conv_node::type>(details->conv, node.type);
-            member ? (*member = node) : details->conv.emplace_back(node);
+            auto *member = find_member<&meta_conv_node::type>(elem.details->conv, node.type);
+            member ? (*member = node) : elem.details->conv.emplace_back(node);
         } else {
             static_assert(std::is_same_v<Type, meta_ctor_node>, "Unexpected type");
-            auto *member = find_member<&meta_ctor_node::id>(details->ctor, node.id);
-            member ? (*member = node) : details->ctor.emplace_back(node);
+            auto *member = find_member<&meta_ctor_node::id>(elem.details->ctor, node.id);
+            member ? (*member = node) : elem.details->ctor.emplace_back(node);
         }
     }
 
     void data(meta_data_node node) {
+        auto &elem = fetch_node();
+
         reset_bucket(node.id);
 
-        if(auto *member = find_member<&meta_data_node::id>(details->data, node.id); member == nullptr) {
-            details->data.emplace_back(std::move(node));
+        if(auto *member = find_member<&meta_data_node::id>(elem.details->data, node.id); member == nullptr) {
+            elem.details->data.emplace_back(std::move(node));
         } else if(member->set != node.set || member->get != node.get) {
             *member = std::move(node);
         }
     }
 
     void func(meta_func_node node) {
+        auto &elem = fetch_node();
+
         reset_bucket(node.id, node.invoke);
 
-        if(auto *member = find_member<&meta_func_node::id>(details->func, node.id); member == nullptr) {
-            details->func.emplace_back(std::move(node));
+        if(auto *member = find_member<&meta_func_node::id>(elem.details->func, node.id); member == nullptr) {
+            elem.details->func.emplace_back(std::move(node));
         } else if(auto *overload = find_overload(member, node.invoke); overload == nullptr) {
             while(member->next != nullptr) { member = member->next.get(); }
             member->next = std::make_unique<meta_func_node>(std::move(node));
@@ -98,7 +108,7 @@ protected:
 
     void traits(const meta_traits value) {
         if(bucket == parent) {
-            meta_context::from(*ctx).value[bucket].traits |= value;
+            fetch_node().traits |= value;
         } else if(invoke == nullptr) {
             find_member_or_assert()->traits |= value;
         } else {
@@ -108,7 +118,7 @@ protected:
 
     void custom(meta_custom_node node) {
         if(bucket == parent) {
-            details->custom = std::move(node);
+            fetch_node().details->custom = std::move(node);
         } else if(invoke == nullptr) {
             find_member_or_assert()->custom = std::move(node);
         } else {
@@ -117,15 +127,12 @@ protected:
     }
 
 public:
-    basic_meta_factory(meta_ctx &area, meta_type_node node)
+    basic_meta_factory(meta_ctx &area, const meta_type_node &node)
         : ctx{&area},
           parent{node.info->hash()},
-          bucket{parent},
-          details{node.details.get()} {
-        if(details == nullptr) {
-            node.details = std::make_shared<meta_type_descriptor>();
-            meta_context::from(*ctx).value[parent] = node;
-            details = node.details.get();
+          bucket{parent} {
+        if(auto &curr = meta_context::from(*ctx).value.try_emplace(parent, node).first->second; curr.details == nullptr) {
+            curr.details = std::make_shared<meta_type_descriptor>();
         }
     }
 
@@ -134,7 +141,6 @@ private:
     id_type parent{};
     id_type bucket{};
     invoke_type *invoke{};
-    meta_type_descriptor *details{};
 };
 
 } // namespace internal

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

@@ -76,8 +76,8 @@ public:
 private:
     const meta_ctx *ctx{};
     const void *data{};
-    internal::meta_type_node (*value_type_node)(const internal::meta_context &){};
-    internal::meta_type_node (*const_reference_node)(const internal::meta_context &){};
+    const internal::meta_type_node &(*value_type_node)(const internal::meta_context &){};
+    const internal::meta_type_node &(*const_reference_node)(const internal::meta_context &){};
     size_type (*size_fn)(const void *){};
     bool (*clear_fn)(void *){};
     bool (*reserve_fn)(void *, const size_type){};
@@ -142,9 +142,9 @@ public:
 private:
     const meta_ctx *ctx{};
     const void *data{};
-    internal::meta_type_node (*key_type_node)(const internal::meta_context &){};
-    internal::meta_type_node (*mapped_type_node)(const internal::meta_context &){};
-    internal::meta_type_node (*value_type_node)(const internal::meta_context &){};
+    const internal::meta_type_node &(*key_type_node)(const internal::meta_context &){};
+    const internal::meta_type_node &(*mapped_type_node)(const internal::meta_context &){};
+    const internal::meta_type_node &(*value_type_node)(const internal::meta_context &){};
     size_type (*size_fn)(const void *){};
     bool (*clear_fn)(void *){};
     bool (*reserve_fn)(void *, const size_type){};
@@ -629,7 +629,7 @@ public:
 private:
     any storage;
     const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
-    internal::meta_type_node (*resolve)(const internal::meta_context &) noexcept {};
+    const internal::meta_type_node &(*resolve)(const internal::meta_context &) noexcept {};
     mutable internal::meta_type_node lazy_node{};
     vtable_type *vtable{};
 };

+ 14 - 13
src/entt/meta/node.hpp

@@ -69,7 +69,7 @@ struct meta_custom_node {
 
 struct meta_base_node {
     id_type type{};
-    meta_type_node (*resolve)(const meta_context &) noexcept {};
+    const meta_type_node &(*resolve)(const meta_context &) noexcept {};
     const void *(*cast)(const void *) noexcept {};
 };
 
@@ -94,7 +94,7 @@ struct meta_data_node {
     const char *name{};
     meta_traits traits{meta_traits::is_none};
     size_type arity{0u};
-    meta_type_node (*type)(const meta_context &) noexcept {};
+    const meta_type_node &(*type)(const meta_context &) noexcept {};
     meta_type (*arg)(const meta_ctx &, const size_type) noexcept {};
     bool (*set)(meta_handle, meta_any){};
     meta_any (*get)(meta_handle){};
@@ -108,7 +108,7 @@ struct meta_func_node {
     const char *name{};
     meta_traits traits{meta_traits::is_none};
     size_type arity{0u};
-    meta_type_node (*ret)(const meta_context &) noexcept {};
+    const meta_type_node &(*ret)(const meta_context &) noexcept {};
     meta_type (*arg)(const meta_ctx &, const size_type) noexcept {};
     meta_any (*invoke)(meta_handle, meta_any *const){};
     std::unique_ptr<meta_func_node> next;
@@ -119,8 +119,8 @@ struct meta_template_node {
     using size_type = std::size_t;
 
     size_type arity{0u};
-    meta_type_node (*resolve)(const meta_context &) noexcept {};
-    meta_type_node (*arg)(const meta_context &, const size_type) noexcept {};
+    const meta_type_node &(*resolve)(const meta_context &) noexcept {};
+    const meta_type_node &(*arg)(const meta_context &, const size_type) noexcept {};
 };
 
 struct meta_type_descriptor {
@@ -140,7 +140,7 @@ struct meta_type_node {
     const char *name{};
     meta_traits traits{meta_traits::is_none};
     size_type size_of{0u};
-    meta_type_node (*remove_pointer)(const meta_context &) noexcept {};
+    const meta_type_node &(*remove_pointer)(const meta_context &) noexcept {};
     meta_any (*default_constructor)(const meta_ctx &){};
     double (*conversion_helper)(void *, const void *){};
     meta_any (*from_void)(const meta_ctx &, void *, const void *){};
@@ -184,11 +184,11 @@ template<auto Member>
 }
 
 template<typename Type>
-meta_type_node resolve(const meta_context &) noexcept;
+const meta_type_node &resolve(const meta_context &) noexcept;
 
 template<typename... Args>
-[[nodiscard]] auto meta_arg_node(const meta_context &context, type_list<Args...>, [[maybe_unused]] const std::size_t index) noexcept {
-    meta_type_node (*value)(const meta_context &) noexcept = nullptr;
+[[nodiscard]] const meta_type_node &meta_arg_node(const meta_context &context, type_list<Args...>, [[maybe_unused]] const std::size_t index) noexcept {
+    const meta_type_node &(*value)(const meta_context &) noexcept = nullptr;
 
     if constexpr(sizeof...(Args) != 0u) {
         std::size_t pos{};
@@ -294,7 +294,7 @@ auto setup_node_for() noexcept {
         node.templ = meta_template_node{
             meta_template_traits<Type>::args_type::size,
             &resolve<typename meta_template_traits<Type>::class_type>,
-            +[](const meta_context &area, const std::size_t index) noexcept { return meta_arg_node(area, typename meta_template_traits<Type>::args_type{}, index); }};
+            +[](const meta_context &area, const std::size_t index) noexcept -> decltype(auto) { return meta_arg_node(area, typename meta_template_traits<Type>::args_type{}, index); }};
     }
 
     return node;
@@ -306,10 +306,11 @@ auto setup_node_for() noexcept {
 }
 
 template<typename Type>
-[[nodiscard]] meta_type_node resolve(const meta_context &context) noexcept {
+[[nodiscard]] const meta_type_node &resolve(const meta_context &context) noexcept {
     static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");
-    const auto *elem = try_resolve(context, type_id<Type>());
-    return (elem == nullptr) ? setup_node_for<Type>() : *elem;
+    static const meta_type_node node = setup_node_for<Type>();
+    const auto *elem = try_resolve(context, *node.info);
+    return (elem == nullptr) ? node : *elem;
 }
 
 } // namespace internal