Merge pull request #71644 from RandomShaper/mq_call_static

Complete support of callables of static methods
This commit is contained in:
Rémi Verschelde 2023-04-12 23:19:27 +02:00 committed by GitHub
commit 5860b02b63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 76 additions and 42 deletions

View File

@ -198,7 +198,7 @@ class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
} data; } data;
public: public:
virtual ObjectID get_object() const { virtual ObjectID get_object() const override {
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) { if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) {
return ObjectID(); return ObjectID();
@ -207,7 +207,7 @@ public:
return data.instance->get_instance_id(); return data.instance->get_instance_id();
} }
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
ERR_FAIL_COND_MSG(ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr, "Invalid Object id '" + uitos(data.object_id) + "', can't call method."); ERR_FAIL_COND_MSG(ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr, "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
#endif #endif
@ -254,11 +254,15 @@ class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase
} data; } data;
public: public:
virtual ObjectID get_object() const { virtual bool is_valid() const override {
return true;
}
virtual ObjectID get_object() const override {
return ObjectID(); return ObjectID();
} }
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error); call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
r_return_value = Variant(); r_return_value = Variant();
} }
@ -292,11 +296,15 @@ class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerB
} data; } data;
public: public:
virtual ObjectID get_object() const { virtual bool is_valid() const override {
return true;
}
virtual ObjectID get_object() const override {
return ObjectID(); return ObjectID();
} }
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error); call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
} }

View File

@ -90,6 +90,10 @@ Error CallQueue::push_callablep(const Callable &p_callable, const Variant **p_ar
if (p_show_error) { if (p_show_error) {
msg->type |= FLAG_SHOW_ERROR; msg->type |= FLAG_SHOW_ERROR;
} }
// Support callables of static methods.
if (p_callable.get_object_id().is_null() && p_callable.is_valid()) {
msg->type |= FLAG_NULL_IS_OK;
}
buffer_end += sizeof(Message); buffer_end += sizeof(Message);
@ -238,28 +242,24 @@ Error CallQueue::flush() {
mutex.unlock(); mutex.unlock();
if (target != nullptr) { switch (message->type & FLAG_MASK) {
switch (message->type & FLAG_MASK) { case TYPE_CALL: {
case TYPE_CALL: { if (target || (message->type & FLAG_NULL_IS_OK)) {
Variant *args = (Variant *)(message + 1); Variant *args = (Variant *)(message + 1);
// messages don't expect a return value
_call_function(message->callable, args, message->args, message->type & FLAG_SHOW_ERROR); _call_function(message->callable, args, message->args, message->type & FLAG_SHOW_ERROR);
}
} break; } break;
case TYPE_NOTIFICATION: { case TYPE_NOTIFICATION: {
// messages don't expect a return value if (target) {
target->notification(message->notification); target->notification(message->notification);
}
} break; } break;
case TYPE_SET: { case TYPE_SET: {
if (target) {
Variant *arg = (Variant *)(message + 1); Variant *arg = (Variant *)(message + 1);
// messages don't expect a return value
target->set(message->callable.get_method(), *arg); target->set(message->callable.get_method(), *arg);
}
} break; } break;
}
} }
if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION) { if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION) {
@ -355,36 +355,41 @@ void CallQueue::statistics() {
Object *target = message->callable.get_object(); Object *target = message->callable.get_object();
if (target != nullptr) { bool null_target = true;
switch (message->type & FLAG_MASK) { switch (message->type & FLAG_MASK) {
case TYPE_CALL: { case TYPE_CALL: {
if (target || (message->type & FLAG_NULL_IS_OK)) {
if (!call_count.has(message->callable)) { if (!call_count.has(message->callable)) {
call_count[message->callable] = 0; call_count[message->callable] = 0;
} }
call_count[message->callable]++; call_count[message->callable]++;
null_target = false;
} break; }
case TYPE_NOTIFICATION: { } break;
case TYPE_NOTIFICATION: {
if (target) {
if (!notify_count.has(message->notification)) { if (!notify_count.has(message->notification)) {
notify_count[message->notification] = 0; notify_count[message->notification] = 0;
} }
notify_count[message->notification]++; notify_count[message->notification]++;
null_target = false;
} break; }
case TYPE_SET: { } break;
case TYPE_SET: {
if (target) {
StringName t = message->callable.get_method(); StringName t = message->callable.get_method();
if (!set_count.has(t)) { if (!set_count.has(t)) {
set_count[t] = 0; set_count[t] = 0;
} }
set_count[t]++; set_count[t]++;
null_target = false;
} break; }
} } break;
}
} else { if (null_target) {
//object was deleted //object was deleted
print_line("Object was deleted while awaiting a callback"); print_line("Object was deleted while awaiting a callback");

View File

@ -51,8 +51,9 @@ private:
TYPE_NOTIFICATION, TYPE_NOTIFICATION,
TYPE_SET, TYPE_SET,
TYPE_END, // End marker. TYPE_END, // End marker.
FLAG_NULL_IS_OK = 1 << 13,
FLAG_SHOW_ERROR = 1 << 14, FLAG_SHOW_ERROR = 1 << 14,
FLAG_MASK = FLAG_SHOW_ERROR - 1, FLAG_MASK = FLAG_NULL_IS_OK - 1,
}; };
struct Page { struct Page {

View File

@ -122,7 +122,11 @@ Callable Callable::unbind(int p_argcount) const {
} }
bool Callable::is_valid() const { bool Callable::is_valid() const {
return get_object() && (is_custom() || get_object()->has_method(get_method())); if (is_custom()) {
return get_custom()->is_valid();
} else {
return get_object() && get_object()->has_method(get_method());
}
} }
Object *Callable::get_object() const { Object *Callable::get_object() const {
@ -373,6 +377,11 @@ Callable::~Callable() {
} }
} }
bool CallableCustom::is_valid() const {
// Sensible default implementation so most custom callables don't need their own.
return ObjectDB::get_instance(get_object());
}
StringName CallableCustom::get_method() const { StringName CallableCustom::get_method() const {
ERR_FAIL_V_MSG(StringName(), vformat("Can't get method on CallableCustom \"%s\".", get_as_text())); ERR_FAIL_V_MSG(StringName(), vformat("Can't get method on CallableCustom \"%s\".", get_as_text()));
} }

View File

@ -145,8 +145,9 @@ public:
virtual String get_as_text() const = 0; virtual String get_as_text() const = 0;
virtual CompareEqualFunc get_compare_equal_func() const = 0; virtual CompareEqualFunc get_compare_equal_func() const = 0;
virtual CompareLessFunc get_compare_less_func() const = 0; virtual CompareLessFunc get_compare_less_func() const = 0;
virtual bool is_valid() const;
virtual StringName get_method() const; virtual StringName get_method() const;
virtual ObjectID get_object() const = 0; //must always be able to provide an object virtual ObjectID get_object() const = 0;
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const = 0; virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const = 0;
virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const; virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const;
virtual const Callable *get_base_comparator() const; virtual const Callable *get_base_comparator() const;

View File

@ -75,6 +75,10 @@ CallableCustom::CompareLessFunc CallableCustomBind::get_compare_less_func() cons
return _less_func; return _less_func;
} }
bool CallableCustomBind::is_valid() const {
return callable.is_valid();
}
StringName CallableCustomBind::get_method() const { StringName CallableCustomBind::get_method() const {
return callable.get_method(); return callable.get_method();
} }
@ -193,6 +197,10 @@ CallableCustom::CompareLessFunc CallableCustomUnbind::get_compare_less_func() co
return _less_func; return _less_func;
} }
bool CallableCustomUnbind::is_valid() const {
return callable.is_valid();
}
StringName CallableCustomUnbind::get_method() const { StringName CallableCustomUnbind::get_method() const {
return callable.get_method(); return callable.get_method();
} }

View File

@ -47,8 +47,9 @@ public:
virtual String get_as_text() const override; virtual String get_as_text() const override;
virtual CompareEqualFunc get_compare_equal_func() const override; virtual CompareEqualFunc get_compare_equal_func() const override;
virtual CompareLessFunc get_compare_less_func() const override; virtual CompareLessFunc get_compare_less_func() const override;
virtual bool is_valid() const override;
virtual StringName get_method() const override; virtual StringName get_method() const override;
virtual ObjectID get_object() const override; //must always be able to provide an object virtual ObjectID get_object() const override;
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override; virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
virtual const Callable *get_base_comparator() const override; virtual const Callable *get_base_comparator() const override;
virtual int get_bound_arguments_count() const override; virtual int get_bound_arguments_count() const override;
@ -73,8 +74,9 @@ public:
virtual String get_as_text() const override; virtual String get_as_text() const override;
virtual CompareEqualFunc get_compare_equal_func() const override; virtual CompareEqualFunc get_compare_equal_func() const override;
virtual CompareLessFunc get_compare_less_func() const override; virtual CompareLessFunc get_compare_less_func() const override;
virtual bool is_valid() const override;
virtual StringName get_method() const override; virtual StringName get_method() const override;
virtual ObjectID get_object() const override; //must always be able to provide an object virtual ObjectID get_object() const override;
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override; virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
virtual const Callable *get_base_comparator() const override; virtual const Callable *get_base_comparator() const override;
virtual int get_bound_arguments_count() const override; virtual int get_bound_arguments_count() const override;