Преглед изворни кода

Re-add resource thread-safety measures

These deferring measures were added to aid threaded resource loading in being safe.

They were removed as seemingly unneeded, but it seems they are needed so resources involved in threaded loading interact with others only after "sync points".
Pedro J. Estébanez пре 1 година
родитељ
комит
62d9ce6445
1 измењених фајлова са 16 додато и 1 уклоњено
  1. 16 1
      core/io/resource.cpp

+ 16 - 1
core/io/resource.cpp

@@ -40,7 +40,12 @@
 #include <stdio.h>
 #include <stdio.h>
 
 
 void Resource::emit_changed() {
 void Resource::emit_changed() {
-	emit_signal(CoreStringName(changed));
+	if (ResourceLoader::is_within_load() && MessageQueue::get_main_singleton() != MessageQueue::get_singleton() && !MessageQueue::get_singleton()->is_flushing()) {
+		// Let the connection happen on the call queue, later, since signals are not thread-safe.
+		call_deferred("emit_signal", CoreStringName(changed));
+	} else {
+		emit_signal(CoreStringName(changed));
+	}
 }
 }
 
 
 void Resource::_resource_path_changed() {
 void Resource::_resource_path_changed() {
@@ -161,12 +166,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() && MessageQueue::get_main_singleton() != MessageQueue::get_singleton() && !MessageQueue::get_singleton()->is_flushing()) {
+		// Let the check and connection happen on the call queue, later, since signals are not thread-safe.
+		callable_mp(this, &Resource::connect_changed).call_deferred(p_callable, p_flags);
+		return;
+	}
 	if (!is_connected(CoreStringName(changed), p_callable) || p_flags & CONNECT_REFERENCE_COUNTED) {
 	if (!is_connected(CoreStringName(changed), p_callable) || p_flags & CONNECT_REFERENCE_COUNTED) {
 		connect(CoreStringName(changed), p_callable, p_flags);
 		connect(CoreStringName(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() && MessageQueue::get_main_singleton() != MessageQueue::get_singleton() && !MessageQueue::get_singleton()->is_flushing()) {
+		// Let the check and disconnection happen on the call queue, later, since signals are not thread-safe.
+		callable_mp(this, &Resource::disconnect_changed).call_deferred(p_callable);
+		return;
+	}
 	if (is_connected(CoreStringName(changed), p_callable)) {
 	if (is_connected(CoreStringName(changed), p_callable)) {
 		disconnect(CoreStringName(changed), p_callable);
 		disconnect(CoreStringName(changed), p_callable);
 	}
 	}