summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPedro J. Estébanez <pedrojrulez@gmail.com>2024-07-12 16:03:01 +0200
committerPedro J. Estébanez <pedrojrulez@gmail.com>2024-07-15 12:15:22 +0200
commit62d9ce6445283d2bc1daa973350f91df56a826bf (patch)
tree9c48b7a6c39f76c5679f2155c8d18eb044694471
parent26d1577f3985363faab48a65e9a0d9eed0e26d86 (diff)
downloadredot-engine-62d9ce6445283d2bc1daa973350f91df56a826bf.tar.gz
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".
-rw-r--r--core/io/resource.cpp17
1 files changed, 16 insertions, 1 deletions
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index c045c0fc74..432adb88da 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -40,7 +40,12 @@
#include <stdio.h>
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() {
@@ -161,12 +166,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() && 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) {
connect(CoreStringName(changed), p_callable, p_flags);
}
}
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)) {
disconnect(CoreStringName(changed), p_callable);
}