summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormyaaaaaaaaa <103326468+myaaaaaaaaa@users.noreply.github.com>2023-01-29 20:46:55 -0500
committermyaaaaaaaaa <103326468+myaaaaaaaaa@users.noreply.github.com>2023-06-20 08:40:01 -0400
commit5cc961627de43b592b1c69c5367d7ab9fb43a732 (patch)
tree686e3226f8d7c73ab046a4ed7461b4e87505afd8
parent668cf3c66f42989949399f36e9faa29426e37416 (diff)
downloadredot-engine-5cc961627de43b592b1c69c5367d7ab9fb43a732.tar.gz
Avoid sorting CallableCustomMethodPointers by their actual address values
-rw-r--r--core/object/callable_method_pointer.cpp22
-rw-r--r--tests/core/object/test_object.h23
2 files changed, 29 insertions, 16 deletions
diff --git a/core/object/callable_method_pointer.cpp b/core/object/callable_method_pointer.cpp
index b53985e6b7..ed400788b1 100644
--- a/core/object/callable_method_pointer.cpp
+++ b/core/object/callable_method_pointer.cpp
@@ -38,13 +38,10 @@ bool CallableCustomMethodPointerBase::compare_equal(const CallableCustom *p_a, c
return false;
}
- for (uint32_t i = 0; i < a->comp_size; i++) {
- if (a->comp_ptr[i] != b->comp_ptr[i]) {
- return false;
- }
- }
-
- return true;
+ // Avoid sorting by memory address proximity, which leads to unpredictable performance over time
+ // due to the reuse of old addresses for newer objects. Use byte-wise comparison to leverage the
+ // backwards encoding of little-endian systems as a way to decouple spatiality and time.
+ return memcmp(a->comp_ptr, b->comp_ptr, a->comp_size * 4) == 0;
}
bool CallableCustomMethodPointerBase::compare_less(const CallableCustom *p_a, const CallableCustom *p_b) {
@@ -55,15 +52,8 @@ bool CallableCustomMethodPointerBase::compare_less(const CallableCustom *p_a, co
return a->comp_size < b->comp_size;
}
- for (uint32_t i = 0; i < a->comp_size; i++) {
- if (a->comp_ptr[i] == b->comp_ptr[i]) {
- continue;
- }
-
- return a->comp_ptr[i] < b->comp_ptr[i];
- }
-
- return false;
+ // See note in compare_equal().
+ return memcmp(a->comp_ptr, b->comp_ptr, a->comp_size * 4) < 0;
}
CallableCustom::CompareEqualFunc CallableCustomMethodPointerBase::get_compare_equal_func() const {
diff --git a/tests/core/object/test_object.h b/tests/core/object/test_object.h
index 98f9b3da65..8ab6221a1c 100644
--- a/tests/core/object/test_object.h
+++ b/tests/core/object/test_object.h
@@ -399,6 +399,29 @@ TEST_CASE("[Object] Signals") {
SIGNAL_CHECK("my_custom_signal", empty_signal_args);
SIGNAL_UNWATCH(&object, "my_custom_signal");
}
+
+ SUBCASE("Connecting and then disconnecting many signals should not leave anything behind") {
+ List<Object::Connection> signal_connections;
+ Object targets[100];
+
+ for (int i = 0; i < 10; i++) {
+ ERR_PRINT_OFF;
+ for (Object &target : targets) {
+ object.connect("my_custom_signal", callable_mp(&target, &Object::notify_property_list_changed));
+ }
+ ERR_PRINT_ON;
+ signal_connections.clear();
+ object.get_all_signal_connections(&signal_connections);
+ CHECK(signal_connections.size() == 100);
+ }
+
+ for (Object &target : targets) {
+ object.disconnect("my_custom_signal", callable_mp(&target, &Object::notify_property_list_changed));
+ }
+ signal_connections.clear();
+ object.get_all_signal_connections(&signal_connections);
+ CHECK(signal_connections.size() == 0);
+ }
}
} // namespace TestObject