summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2019-02-16 17:38:09 -0300
committerJuan Linietsky <reduzio@gmail.com>2019-02-16 17:39:06 -0300
commit1f9c54bd55a914c8126e4c9954ad648cdeddacb1 (patch)
treefcce819e1183dc8f2d020f1cb74963734b709f11
parent0a563bfab1ec1dd2f3d4f68bb5c5fa226b3dd02d (diff)
Make resource loader cycle checker work on a per-thread basis.
This removes editor errors saying cycles existed when the thumbnailer was running.
-rw-r--r--core/io/resource_loader.cpp40
-rw-r--r--core/io/resource_loader.h20
2 files changed, 51 insertions, 9 deletions
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 4aa002e9a2..10a32bae41 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -55,7 +55,7 @@ Error ResourceInteractiveLoader::wait() {
ResourceInteractiveLoader::~ResourceInteractiveLoader() {
if (path_loading != String()) {
- ResourceLoader::_remove_from_loading_map(path_loading);
+ ResourceLoader::_remove_from_loading_map_and_thread(path_loading, path_loading_thread);
}
}
@@ -293,10 +293,14 @@ bool ResourceLoader::_add_to_loading_map(const String &p_path) {
loading_map_mutex->lock();
}
- if (loading_map.has(p_path)) {
+ LoadingMapKey key;
+ key.path = p_path;
+ key.thread = Thread::get_caller_id();
+
+ if (loading_map.has(key)) {
success = false;
} else {
- loading_map[p_path] = true;
+ loading_map[key] = true;
success = true;
}
@@ -312,7 +316,27 @@ void ResourceLoader::_remove_from_loading_map(const String &p_path) {
loading_map_mutex->lock();
}
- loading_map.erase(p_path);
+ LoadingMapKey key;
+ key.path = p_path;
+ key.thread = Thread::get_caller_id();
+
+ loading_map.erase(key);
+
+ if (loading_map_mutex) {
+ loading_map_mutex->unlock();
+ }
+}
+
+void ResourceLoader::_remove_from_loading_map_and_thread(const String &p_path, Thread::ID p_thread) {
+ if (loading_map_mutex) {
+ loading_map_mutex->lock();
+ }
+
+ LoadingMapKey key;
+ key.path = p_path;
+ key.thread = p_thread;
+
+ loading_map.erase(key);
if (loading_map_mutex) {
loading_map_mutex->unlock();
@@ -471,6 +495,7 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_
ril->resource = res_cached;
ril->path_loading = local_path;
+ ril->path_loading_thread = Thread::get_caller_id();
return ril;
}
}
@@ -499,6 +524,7 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_
if (!p_no_cache) {
ril->set_local_path(local_path);
ril->path_loading = local_path;
+ ril->path_loading_thread = Thread::get_caller_id();
}
if (xl_remapped)
@@ -919,7 +945,7 @@ void ResourceLoader::remove_custom_loaders() {
}
Mutex *ResourceLoader::loading_map_mutex = NULL;
-HashMap<String, int> ResourceLoader::loading_map;
+HashMap<ResourceLoader::LoadingMapKey, int, ResourceLoader::LoadingMapKeyHasher> ResourceLoader::loading_map;
void ResourceLoader::initialize() {
#ifndef NO_THREADS
@@ -929,9 +955,9 @@ void ResourceLoader::initialize() {
void ResourceLoader::finalize() {
#ifndef NO_THREADS
- const String *K = NULL;
+ const LoadingMapKey *K = NULL;
while ((K = loading_map.next(K))) {
- ERR_PRINTS("Exited while resource is being loaded: " + *K);
+ ERR_PRINTS("Exited while resource is being loaded: " + K->path);
}
loading_map.clear();
memdelete(loading_map_mutex);
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index 622b74a998..70eb1a3de0 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -31,8 +31,8 @@
#ifndef RESOURCE_LOADER_H
#define RESOURCE_LOADER_H
+#include "core/os/thread.h"
#include "core/resource.h"
-
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -42,6 +42,7 @@ class ResourceInteractiveLoader : public Reference {
GDCLASS(ResourceInteractiveLoader, Reference);
friend class ResourceLoader;
String path_loading;
+ Thread::ID path_loading_thread;
protected:
static void _bind_methods();
@@ -121,10 +122,25 @@ class ResourceLoader {
static Ref<ResourceFormatLoader> _find_custom_resource_format_loader(String path);
static Mutex *loading_map_mutex;
- static HashMap<String, int> loading_map;
+
+ //used to track paths being loaded in a thread, avoids cyclic recursion
+ struct LoadingMapKey {
+ String path;
+ Thread::ID thread;
+ bool operator==(const LoadingMapKey &p_key) const {
+ return (thread == p_key.thread && path == p_key.path);
+ }
+ };
+ struct LoadingMapKeyHasher {
+
+ static _FORCE_INLINE_ uint32_t hash(const LoadingMapKey &p_key) { return p_key.path.hash() + HashMapHasherDefault::hash(p_key.thread); }
+ };
+
+ static HashMap<LoadingMapKey, int, LoadingMapKeyHasher> loading_map;
static bool _add_to_loading_map(const String &p_path);
static void _remove_from_loading_map(const String &p_path);
+ static void _remove_from_loading_map_and_thread(const String &p_path, Thread::ID p_thread);
public:
static Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL);