Skip to content

Commit

Permalink
Make languages' thread enter/exit more resilient
Browse files Browse the repository at this point in the history
  • Loading branch information
RandomShaper committed Sep 10, 2024
1 parent 2d1dd41 commit 2a86da4
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 7 deletions.
17 changes: 17 additions & 0 deletions core/object/script_language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ ScriptLanguage *ScriptServer::_languages[MAX_LANGUAGES];
int ScriptServer::_language_count = 0;
bool ScriptServer::languages_ready = false;
Mutex ScriptServer::languages_mutex;
thread_local bool ScriptServer::thread_entered = false;

bool ScriptServer::scripting_enabled = true;
bool ScriptServer::reload_scripts_on_save = false;
Expand Down Expand Up @@ -326,6 +327,10 @@ bool ScriptServer::are_languages_initialized() {
return languages_ready;
}

bool ScriptServer::thread_is_entered() {
return thread_entered;
}

void ScriptServer::set_reload_scripts_on_save(bool p_enable) {
reload_scripts_on_save = p_enable;
}
Expand All @@ -335,23 +340,35 @@ bool ScriptServer::is_reload_scripts_on_save_enabled() {
}

void ScriptServer::thread_enter() {
if (thread_entered) {
return;
}

MutexLock lock(languages_mutex);
if (!languages_ready) {
return;
}
for (int i = 0; i < _language_count; i++) {
_languages[i]->thread_enter();
}

thread_entered = true;
}

void ScriptServer::thread_exit() {
if (!thread_entered) {
return;
}

MutexLock lock(languages_mutex);
if (!languages_ready) {
return;
}
for (int i = 0; i < _language_count; i++) {
_languages[i]->thread_exit();
}

thread_entered = false;
}

HashMap<StringName, ScriptServer::GlobalScriptClass> ScriptServer::global_classes;
Expand Down
2 changes: 2 additions & 0 deletions core/object/script_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class ScriptServer {
static int _language_count;
static bool languages_ready;
static Mutex languages_mutex;
static thread_local bool thread_entered;

static bool scripting_enabled;
static bool reload_scripts_on_save;
Expand Down Expand Up @@ -101,6 +102,7 @@ class ScriptServer {
static void init_languages();
static void finish_languages();
static bool are_languages_initialized();
static bool thread_is_entered();
};

class PlaceHolderScriptInstance;
Expand Down
10 changes: 5 additions & 5 deletions core/object/worker_thread_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,17 @@ void WorkerThreadPool::_process_task(Task *p_task) {
// Tasks must start with these at default values. They are free to set-and-forget otherwise.
set_current_thread_safe_for_nodes(false);
MessageQueue::set_thread_singleton_override(nullptr);

// Since the WorkerThreadPool is started before the script server,
// its pre-created threads can't have ScriptServer::thread_enter() called on them early.
// Therefore, we do it late at the first opportunity, so in case the task
// about to be run uses scripting, guarantees are held.
task_mutex.lock();
if (!curr_thread.ready_for_scripting && ScriptServer::are_languages_initialized()) {
task_mutex.unlock();
if (!ScriptServer::thread_is_entered() && // Checking this first is an optimization (no locks, just TLS bool check).
ScriptServer::are_languages_initialized()) {
ScriptServer::thread_enter();
task_mutex.lock();
curr_thread.ready_for_scripting = true;
}

task_mutex.lock();
p_task->pool_thread_index = pool_thread_index;
prev_task = curr_thread.current_task;
curr_thread.current_task = p_task;
Expand Down
2 changes: 0 additions & 2 deletions core/object/worker_thread_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,13 @@ class WorkerThreadPool : public Object {

uint32_t index = 0;
Thread thread;
bool ready_for_scripting : 1;
bool signaled : 1;
bool yield_is_over : 1;
Task *current_task = nullptr;
Task *awaited_task = nullptr; // Null if not awaiting the condition variable, or special value (YIELDING).
ConditionVariable cond_var;

ThreadData() :
ready_for_scripting(false),
signaled(false),
yield_is_over(false) {}
};
Expand Down

0 comments on commit 2a86da4

Please sign in to comment.