meta: reduce cost of meta func
This commit is contained in:
@@ -38,13 +38,15 @@ class basic_meta_factory {
|
||||
}
|
||||
|
||||
static auto *find_overload(meta_func_node *curr, invoke_type *const ref) {
|
||||
for(; curr->invoke != ref; curr = curr->next.get()) {}
|
||||
ENTT_ASSERT(curr != nullptr, "Cannot find overload");
|
||||
while(curr && (curr->invoke != ref)) {
|
||||
curr = curr->next.get();
|
||||
}
|
||||
|
||||
return curr;
|
||||
}
|
||||
|
||||
void reset_bucket(const id_type id) {
|
||||
invoke = nullptr;
|
||||
void reset_bucket(const id_type id, invoke_type *const ref = nullptr) {
|
||||
invoke = ref;
|
||||
bucket = id;
|
||||
}
|
||||
|
||||
@@ -90,25 +92,16 @@ protected:
|
||||
}
|
||||
|
||||
void func(meta_func_node node) {
|
||||
reset_bucket(node.id);
|
||||
reset_bucket(node.id, node.invoke);
|
||||
|
||||
if(auto it = details->func.find(node.id); it == details->func.end()) {
|
||||
auto &&elem = details->func.insert_or_assign(node.id, std::move(node)).first;
|
||||
invoke = elem->second.invoke;
|
||||
} else {
|
||||
auto *curr = &it->second;
|
||||
|
||||
while(curr->invoke != node.invoke && curr->next) {
|
||||
curr = curr->next.get();
|
||||
if(auto *member = find_member(details->func, node.id); member == nullptr) {
|
||||
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();
|
||||
}
|
||||
|
||||
if(curr->invoke == node.invoke) {
|
||||
invoke = curr->invoke;
|
||||
} else {
|
||||
invoke = node.invoke;
|
||||
curr->next = std::make_shared<meta_func_node>();
|
||||
*curr->next = std::move(node);
|
||||
}
|
||||
member->next = std::make_shared<meta_func_node>(std::move(node));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +113,7 @@ protected:
|
||||
} else if(invoke == nullptr) {
|
||||
container = &find_member(details->data, bucket)->prop;
|
||||
} else {
|
||||
container = &find_overload(&details->func[bucket], invoke)->prop; // wait until func is a vector too: find_member(details->func, bucket);
|
||||
container = &find_overload(find_member(details->func, bucket), invoke)->prop;
|
||||
}
|
||||
|
||||
std::size_t pos{};
|
||||
@@ -134,7 +127,7 @@ protected:
|
||||
} else if(invoke == nullptr) {
|
||||
find_member(details->data, bucket)->traits |= value;
|
||||
} else {
|
||||
find_overload(&details->func[bucket], invoke)->traits |= value; // wait until func is a vector too: find_member(details->func, bucket);
|
||||
find_overload(find_member(details->func, bucket), invoke)->traits |= value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +137,7 @@ protected:
|
||||
} else if(invoke == nullptr) {
|
||||
find_member(details->data, bucket)->custom = std::move(node);
|
||||
} else {
|
||||
find_overload(&details->func[bucket], invoke)->custom = std::move(node); // wait until func is a vector too: find_member(details->func, bucket);
|
||||
find_overload(find_member(details->func, bucket), invoke)->custom = std::move(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1454,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::deprecated_look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node, id);
|
||||
const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node, id);
|
||||
return elem ? meta_func{*ctx, *elem} : meta_func{};
|
||||
}
|
||||
|
||||
@@ -1514,9 +1514,13 @@ public:
|
||||
*/
|
||||
meta_any invoke(const id_type id, meta_handle instance, meta_any *const args, const size_type sz) const {
|
||||
if(node.details) {
|
||||
if(auto it = node.details->func.find(id); it != node.details->func.cend()) {
|
||||
if(const auto *candidate = lookup(args, sz, instance && (instance->data() == nullptr), [curr = &it->second]() mutable { return curr ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) {
|
||||
return candidate->invoke(*ctx, meta_handle{*ctx, std::move(instance)}, args);
|
||||
for(auto &&elem: node.details->func) {
|
||||
if(elem.id == id) {
|
||||
if(const auto *candidate = lookup(args, sz, instance && (instance->data() == nullptr), [curr = &elem]() mutable { return curr ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) {
|
||||
return candidate->invoke(*ctx, meta_handle{*ctx, std::move(instance)}, args);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ struct meta_type_descriptor {
|
||||
dense_map<id_type, meta_base_node, identity> base{};
|
||||
std::vector<meta_conv_node> conv{};
|
||||
std::vector<meta_data_node> data{};
|
||||
dense_map<id_type, meta_func_node, identity> func{};
|
||||
std::vector<meta_func_node> func{};
|
||||
std::vector<meta_prop_node> prop{};
|
||||
};
|
||||
|
||||
@@ -161,23 +161,6 @@ struct meta_type_node {
|
||||
std::shared_ptr<meta_type_descriptor> details{};
|
||||
};
|
||||
|
||||
template<auto Member>
|
||||
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 = deprecated_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)>::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) {
|
||||
|
||||
Reference in New Issue
Block a user