Browse Source

Improve thread safety of resource loading

Pedro J. Estébanez 1 year ago
parent
commit
84b85d894c
1 changed files with 16 additions and 1 deletions
  1. 16 1
      core/io/resource.cpp

+ 16 - 1
core/io/resource.cpp

@@ -41,7 +41,12 @@
 #include <stdio.h>
 
 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() {
@@ -152,12 +157,22 @@ bool Resource::editor_can_reload_from_file() {
 }
 
 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) {
 		connect(CoreStringNames::get_singleton()->changed, p_callable, p_flags);
 	}
 }
 
 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)) {
 		disconnect(CoreStringNames::get_singleton()->changed, p_callable);
 	}