Browse Source

meta: persistent bucket in the factory class

Michele Caini 1 year ago
parent
commit
ca0202934c
2 changed files with 36 additions and 26 deletions
  1. 1 0
      TODO
  2. 35 26
      src/entt/meta/factory.hpp

+ 1 - 0
TODO

@@ -47,3 +47,4 @@ TODO:
 * suppress -Wself-move on CI with g++13
 * suppress -Wself-move on CI with g++13
 * meta: custom data can be attached to wrong func if overloaded and re-run/seek (fix and test)
 * meta: custom data can be attached to wrong func if overloaded and re-run/seek (fix and test)
 * meta: use common base node class in the factory for custom/prop
 * meta: use common base node class in the factory for custom/prop
+* meta: drop seek functions, too tricky to support unfortunately

+ 35 - 26
src/entt/meta/factory.hpp

@@ -31,57 +31,68 @@ class basic_meta_factory {
 protected:
 protected:
     void type(const id_type id) noexcept {
     void type(const id_type id) noexcept {
         ENTT_ASSERT(owner->id == id || !resolve(*ctx, id), "Duplicate identifier");
         ENTT_ASSERT(owner->id == id || !resolve(*ctx, id), "Duplicate identifier");
-        bucket = parent;
+        bucket = &owner->details->prop;
+        dest = parent;
         owner->id = id;
         owner->id = id;
     }
     }
 
 
     void base(const id_type id, meta_base_node node) {
     void base(const id_type id, meta_base_node node) {
         owner->details->base.insert_or_assign(id, node);
         owner->details->base.insert_or_assign(id, node);
-        bucket = parent;
+        bucket = nullptr;
+        dest = parent;
     }
     }
 
 
     void conv(const id_type id, meta_conv_node node) {
     void conv(const id_type id, meta_conv_node node) {
         owner->details->conv.insert_or_assign(id, node);
         owner->details->conv.insert_or_assign(id, node);
-        bucket = parent;
+        bucket = nullptr;
+        dest = parent;
     }
     }
 
 
     void ctor(const id_type id, meta_ctor_node node) {
     void ctor(const id_type id, meta_ctor_node node) {
         owner->details->ctor.insert_or_assign(id, node);
         owner->details->ctor.insert_or_assign(id, node);
-        bucket = parent;
+        bucket = nullptr;
+        dest = parent;
     }
     }
 
 
     void dtor(meta_dtor_node node) {
     void dtor(meta_dtor_node node) {
         owner->dtor = node;
         owner->dtor = node;
-        bucket = parent;
+        bucket = nullptr;
+        dest = parent;
     }
     }
 
 
     void data(const id_type id) {
     void data(const id_type id) {
         ENTT_ASSERT(owner->details->data.contains(id), "Invalid id");
         ENTT_ASSERT(owner->details->data.contains(id), "Invalid id");
+        auto &&elem = owner->details->data[id];
+        bucket = &elem.prop;
         is_data = true;
         is_data = true;
-        bucket = id;
+        dest = id;
     }
     }
 
 
     void data(const id_type id, meta_data_node node) {
     void data(const id_type id, meta_data_node node) {
-        owner->details->data.insert_or_assign(id, std::move(node));
+        auto &&it = owner->details->data.insert_or_assign(id, std::move(node)).first;
+        bucket = &it->second.prop;
         is_data = true;
         is_data = true;
-        bucket = id;
+        dest = id;
     }
     }
 
 
     void func(const id_type id) {
     void func(const id_type id) {
         ENTT_ASSERT(owner->details->func.contains(id), "Invalid id");
         ENTT_ASSERT(owner->details->func.contains(id), "Invalid id");
+        auto &&elem = owner->details->func[id];
+        bucket = &elem.prop;
         is_data = false;
         is_data = false;
-        bucket = id;
+        dest = id;
     }
     }
 
 
     void func(const id_type id, meta_func_node node) {
     void func(const id_type id, meta_func_node node) {
         is_data = false;
         is_data = false;
-        bucket = id;
+        dest = id;
 
 
         if(auto it = owner->details->func.find(id); it != owner->details->func.end()) {
         if(auto it = owner->details->func.find(id); it != owner->details->func.end()) {
             for(auto *curr = &it->second; curr; curr = curr->next.get()) {
             for(auto *curr = &it->second; curr; curr = curr->next.get()) {
                 if(curr->invoke == node.invoke) {
                 if(curr->invoke == node.invoke) {
                     node.next = std::move(curr->next);
                     node.next = std::move(curr->next);
                     *curr = std::move(node);
                     *curr = std::move(node);
+                    bucket = &curr->prop;
                     return;
                     return;
                 }
                 }
             }
             }
@@ -90,36 +101,31 @@ protected:
             node.next = std::make_shared<meta_func_node>(std::move(owner->details->func[id]));
             node.next = std::make_shared<meta_func_node>(std::move(owner->details->func[id]));
         }
         }
 
 
-        owner->details->func.insert_or_assign(id, std::move(node));
+        auto &&it = owner->details->func.insert_or_assign(id, std::move(node)).first;
+        bucket = &it->second.prop;
     }
     }
 
 
     void prop(const id_type key, internal::meta_prop_node value) {
     void prop(const id_type key, internal::meta_prop_node value) {
-        if(bucket == parent) {
-            owner->details->prop[key] = std::move(value);
-        } else if(is_data) {
-            owner->details->data[bucket].prop[key] = std::move(value);
-        } else {
-            owner->details->func[bucket].prop[key] = std::move(value);
-        }
+        (*bucket)[key] = std::move(value);
     }
     }
 
 
     void traits(const internal::meta_traits value) {
     void traits(const internal::meta_traits value) {
-        if(bucket == parent) {
+        if(dest == parent) {
             owner->traits |= value;
             owner->traits |= value;
         } else if(is_data) {
         } else if(is_data) {
-            owner->details->data[bucket].traits |= value;
+            owner->details->data[dest].traits |= value;
         } else {
         } else {
-            owner->details->func[bucket].traits |= value;
+            owner->details->func[dest].traits |= value;
         }
         }
     }
     }
 
 
     void custom(meta_custom_node node) {
     void custom(meta_custom_node node) {
-        if(bucket == parent) {
+        if(dest == parent) {
             owner->custom = std::move(node);
             owner->custom = std::move(node);
         } else if(is_data) {
         } else if(is_data) {
-            owner->details->data[bucket].custom = std::move(node);
+            owner->details->data[dest].custom = std::move(node);
         } else {
         } else {
-            owner->details->func[bucket].custom = std::move(node);
+            owner->details->func[dest].custom = std::move(node);
         }
         }
     }
     }
 
 
@@ -128,17 +134,20 @@ public:
         : ctx{&area},
         : ctx{&area},
           owner{&elem},
           owner{&elem},
           parent{elem.info->hash()},
           parent{elem.info->hash()},
-          bucket{elem.info->hash()} {
+          dest{elem.info->hash()} {
         if(!owner->details) {
         if(!owner->details) {
             owner->details = std::make_shared<internal::meta_type_descriptor>();
             owner->details = std::make_shared<internal::meta_type_descriptor>();
         }
         }
+
+        bucket = &owner->details->prop;
     }
     }
 
 
 private:
 private:
     meta_ctx *ctx{};
     meta_ctx *ctx{};
     internal::meta_type_node *owner{};
     internal::meta_type_node *owner{};
+    dense_map<id_type, internal::meta_prop_node, identity> *bucket{};
     const id_type parent{};
     const id_type parent{};
-    id_type bucket{};
+    id_type dest{};
     bool is_data{};
     bool is_data{};
 };
 };