Skip to content

Commit

Permalink
ResourceLoader: Add last resort life-time insurance for tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
RandomShaper committed Sep 5, 2024
1 parent b6223c0 commit 924d829
Showing 1 changed file with 10 additions and 0 deletions.
10 changes: 10 additions & 0 deletions core/io/resource_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_origin
}

// This implementation must allow re-entrancy for a task that started awaiting in a deeper stack frame.
// The load task token must be manually re-referenced before this is called, which includes threaded runs.
void ResourceLoader::_run_load_task(void *p_userdata) {
ThreadLoadTask &load_task = *(ThreadLoadTask *)p_userdata;

Expand Down Expand Up @@ -440,6 +441,9 @@ void ResourceLoader::_run_load_task(void *p_userdata) {
}
}

// It's safe now to let the task go in case no one else was grabbing the token.
load_task.load_token->unreference();

if (unlock_pending) {
thread_load_mutex.unlock();
}
Expand Down Expand Up @@ -593,6 +597,11 @@ Ref<ResourceLoader::LoadToken> ResourceLoader::_load_start(const String &p_path,

run_on_current_thread = must_not_register || p_thread_mode == LOAD_THREAD_FROM_CURRENT;

// It's important to keep the token alive because until the load completes,
// which includes before the thread start, it may happen that no one is grabbing
// the token anymore so it's released.
load_task_ptr->load_token->reference();

if (run_on_current_thread) {
// The current thread may happen to be a thread from the pool.
WorkerThreadPool::TaskID tid = WorkerThreadPool::get_singleton()->get_caller_task_id();
Expand Down Expand Up @@ -777,6 +786,7 @@ Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Erro
// resource loading that means that the task to wait for can be restarted here to break the
// cycle, with as much recursion into this process as needed.
// When the stack is eventually unrolled, the original load will have been notified to go on.
load_task.load_token->reference();
_run_load_task(&load_task);
}

Expand Down

0 comments on commit 924d829

Please sign in to comment.