Make resource loader cycle checker work on a per-thread basis.
This removes editor errors saying cycles existed when the thumbnailer was running.
This commit is contained in:
parent
0a563bfab1
commit
1f9c54bd55
2 changed files with 51 additions and 9 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue