Merge pull request #88561 from RandomShaper/res_load_safer

Improve thread safety of resource loading
This commit is contained in:
Rémi Verschelde 2024-02-29 13:53:58 +01:00
commit 7462b1a0b2
No known key found for this signature in database
GPG key ID: C3336907360768E1

View file

@ -41,7 +41,12 @@
#include <stdio.h> #include <stdio.h>
void Resource::emit_changed() { void Resource::emit_changed() {
emit_signal(CoreStringNames::get_singleton()->changed); if (ResourceLoader::is_within_load() && !Thread::is_main_thread()) {
// Let the connection happen on the main thread, later, since signals are not thread-safe.
call_deferred("emit_signal", CoreStringNames::get_singleton()->changed);
} else {
emit_signal(CoreStringNames::get_singleton()->changed);
}
} }
void Resource::_resource_path_changed() { void Resource::_resource_path_changed() {
@ -152,12 +157,22 @@ bool Resource::editor_can_reload_from_file() {
} }
void Resource::connect_changed(const Callable &p_callable, uint32_t p_flags) { void Resource::connect_changed(const Callable &p_callable, uint32_t p_flags) {
if (ResourceLoader::is_within_load() && !Thread::is_main_thread()) {
// Let the check and connection happen on the main thread, later, since signals are not thread-safe.
callable_mp(this, &Resource::connect_changed).call_deferred(p_callable, p_flags);
return;
}
if (!is_connected(CoreStringNames::get_singleton()->changed, p_callable) || p_flags & CONNECT_REFERENCE_COUNTED) { if (!is_connected(CoreStringNames::get_singleton()->changed, p_callable) || p_flags & CONNECT_REFERENCE_COUNTED) {
connect(CoreStringNames::get_singleton()->changed, p_callable, p_flags); connect(CoreStringNames::get_singleton()->changed, p_callable, p_flags);
} }
} }
void Resource::disconnect_changed(const Callable &p_callable) { void Resource::disconnect_changed(const Callable &p_callable) {
if (ResourceLoader::is_within_load() && !Thread::is_main_thread()) {
// Let the check and disconnection happen on the main thread, later, since signals are not thread-safe.
callable_mp(this, &Resource::disconnect_changed).call_deferred(p_callable);
return;
}
if (is_connected(CoreStringNames::get_singleton()->changed, p_callable)) { if (is_connected(CoreStringNames::get_singleton()->changed, p_callable)) {
disconnect(CoreStringNames::get_singleton()->changed, p_callable); disconnect(CoreStringNames::get_singleton()->changed, p_callable);
} }