mirror of
https://github.com/godotengine/godot.git
synced 2025-12-07 22:00:10 +00:00
ResourceLoader: Fix potential infinite recursion in progress reporting
This commit is contained in:
parent
235a32ad11
commit
5806e3c761
2 changed files with 20 additions and 4 deletions
|
|
@ -666,6 +666,14 @@ Ref<ResourceLoader::LoadToken> ResourceLoader::_load_start(const String &p_path,
|
||||||
float ResourceLoader::_dependency_get_progress(const String &p_path) {
|
float ResourceLoader::_dependency_get_progress(const String &p_path) {
|
||||||
if (thread_load_tasks.has(p_path)) {
|
if (thread_load_tasks.has(p_path)) {
|
||||||
ThreadLoadTask &load_task = thread_load_tasks[p_path];
|
ThreadLoadTask &load_task = thread_load_tasks[p_path];
|
||||||
|
if (load_task.in_progress_check) {
|
||||||
|
// Given the fact that any resource loaded when an outer stack frame is
|
||||||
|
// loading another one is considered a dependency of it, for progress
|
||||||
|
// tracking purposes, a cycle can happen if even if the original resource
|
||||||
|
// graphs involved have none. For instance, preload() can cause this.
|
||||||
|
return load_task.max_reported_progress;
|
||||||
|
}
|
||||||
|
load_task.in_progress_check = true;
|
||||||
float current_progress = 0.0;
|
float current_progress = 0.0;
|
||||||
int dep_count = load_task.sub_tasks.size();
|
int dep_count = load_task.sub_tasks.size();
|
||||||
if (dep_count > 0) {
|
if (dep_count > 0) {
|
||||||
|
|
@ -679,6 +687,7 @@ float ResourceLoader::_dependency_get_progress(const String &p_path) {
|
||||||
current_progress = load_task.progress;
|
current_progress = load_task.progress;
|
||||||
}
|
}
|
||||||
load_task.max_reported_progress = MAX(load_task.max_reported_progress, current_progress);
|
load_task.max_reported_progress = MAX(load_task.max_reported_progress, current_progress);
|
||||||
|
load_task.in_progress_check = false;
|
||||||
return load_task.max_reported_progress;
|
return load_task.max_reported_progress;
|
||||||
} else {
|
} else {
|
||||||
return 1.0; //assume finished loading it so it no longer exists
|
return 1.0; //assume finished loading it so it no longer exists
|
||||||
|
|
|
||||||
|
|
@ -176,10 +176,8 @@ private:
|
||||||
struct ThreadLoadTask {
|
struct ThreadLoadTask {
|
||||||
WorkerThreadPool::TaskID task_id = 0; // Used if run on a worker thread from the pool.
|
WorkerThreadPool::TaskID task_id = 0; // Used if run on a worker thread from the pool.
|
||||||
Thread::ID thread_id = 0; // Used if running on an user thread (e.g., simple non-threaded load).
|
Thread::ID thread_id = 0; // Used if running on an user thread (e.g., simple non-threaded load).
|
||||||
bool awaited = false; // If it's in the pool, this helps not awaiting from more than one dependent thread.
|
|
||||||
ConditionVariable *cond_var = nullptr; // In not in the worker pool or already awaiting, this is used as a secondary awaiting mechanism.
|
ConditionVariable *cond_var = nullptr; // In not in the worker pool or already awaiting, this is used as a secondary awaiting mechanism.
|
||||||
uint32_t awaiters_count = 0;
|
uint32_t awaiters_count = 0;
|
||||||
bool need_wait = true;
|
|
||||||
LoadToken *load_token = nullptr;
|
LoadToken *load_token = nullptr;
|
||||||
String local_path;
|
String local_path;
|
||||||
String type_hint;
|
String type_hint;
|
||||||
|
|
@ -190,17 +188,26 @@ private:
|
||||||
ResourceFormatLoader::CacheMode cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE;
|
ResourceFormatLoader::CacheMode cache_mode = ResourceFormatLoader::CACHE_MODE_REUSE;
|
||||||
Error error = OK;
|
Error error = OK;
|
||||||
Ref<Resource> resource;
|
Ref<Resource> resource;
|
||||||
bool use_sub_threads = false;
|
|
||||||
HashSet<String> sub_tasks;
|
HashSet<String> sub_tasks;
|
||||||
|
|
||||||
|
bool awaited : 1; // If it's in the pool, this helps not awaiting from more than one dependent thread.
|
||||||
|
bool need_wait : 1;
|
||||||
|
bool in_progress_check : 1; // Measure against recursion cycles in progress reporting. Cycles are not expected, but can happen due to how it's currently implemented.
|
||||||
|
bool use_sub_threads : 1;
|
||||||
|
|
||||||
struct ResourceChangedConnection {
|
struct ResourceChangedConnection {
|
||||||
Resource *source = nullptr;
|
Resource *source = nullptr;
|
||||||
Callable callable;
|
Callable callable;
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
};
|
};
|
||||||
LocalVector<ResourceChangedConnection> resource_changed_connections;
|
LocalVector<ResourceChangedConnection> resource_changed_connections;
|
||||||
};
|
|
||||||
|
|
||||||
|
ThreadLoadTask() :
|
||||||
|
awaited(false),
|
||||||
|
need_wait(true),
|
||||||
|
in_progress_check(false),
|
||||||
|
use_sub_threads(false) {}
|
||||||
|
};
|
||||||
static void _run_load_task(void *p_userdata);
|
static void _run_load_task(void *p_userdata);
|
||||||
|
|
||||||
static thread_local bool import_thread;
|
static thread_local bool import_thread;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue