Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add THREADS_ENABLED macro in order to compile Godot to run on the main thread #85939

Merged
merged 1 commit into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions .github/workflows/web_builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,24 @@ concurrency:
jobs:
web-template:
runs-on: "ubuntu-22.04"
name: Template (target=template_release)
name: ${{ matrix.name }}
strategy:
fail-fast: false
matrix:
include:
- name: Template w/ threads (target=template_release, threads=yes)
cache-name: web-template
target: template_release
sconsflags: threads=yes
tests: false
artifact: true

- name: Template w/o threads (target=template_release, threads=no)
cache-name: web-nothreads-template
target: template_release
sconsflags: threads=no
tests: false
artifact: true

steps:
- uses: actions/checkout@v4
Expand All @@ -34,6 +51,8 @@ jobs:

- name: Setup Godot build cache
uses: ./.github/actions/godot-cache
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true

- name: Setup python and scons
Expand All @@ -42,10 +61,13 @@ jobs:
- name: Compilation
uses: ./.github/actions/godot-build
with:
sconsflags: ${{ env.SCONSFLAGS }}
sconsflags: ${{ env.SCONSFLAGS }} ${{ matrix.sconsflags }}
platform: web
target: template_release
tests: false
target: ${{ matrix.target }}
tests: ${{ matrix.tests }}

- name: Upload artifact
uses: ./.github/actions/upload-artifact
if: ${{ matrix.artifact }}
with:
name: ${{ matrix.cache-name }}
8 changes: 8 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ opts.Add(BoolVariable("separate_debug_symbols", "Extract debugging symbols to a
opts.Add(EnumVariable("lto", "Link-time optimization (production builds)", "none", ("none", "auto", "thin", "full")))
opts.Add(BoolVariable("production", "Set defaults to build Godot for use in production", False))
opts.Add(BoolVariable("generate_apk", "Generate an APK/AAB after building Android library by calling Gradle", False))
opts.Add(BoolVariable("threads", "Enable threading support", True))

# Components
opts.Add(BoolVariable("deprecated", "Enable compatibility code for deprecated and removed features", True))
Expand Down Expand Up @@ -832,6 +833,10 @@ if selected_platform in platform_list:
suffix += ".double"

suffix += "." + env["arch"]

if not env["threads"]:
suffix += ".nothreads"

suffix += env.extra_suffix

sys.path.remove(tmppath)
Expand Down Expand Up @@ -972,6 +977,9 @@ if selected_platform in platform_list:
env.Tool("compilation_db")
env.Alias("compiledb", env.CompilationDatabase())

if env["threads"]:
env.Append(CPPDEFINES=["THREADS_ENABLED"])

Export("env")

# Build subdirs, the build order is dependent on link order.
Expand Down
6 changes: 6 additions & 0 deletions core/object/worker_thread_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ WorkerThreadPool *WorkerThreadPool::singleton = nullptr;
thread_local CommandQueueMT *WorkerThreadPool::flushing_cmd_queue = nullptr;

void WorkerThreadPool::_process_task(Task *p_task) {
#ifdef THREADS_ENABLED
int pool_thread_index = thread_ids[Thread::get_caller_id()];
ThreadData &curr_thread = threads[pool_thread_index];
Task *prev_task = nullptr; // In case this is recursively called.
Expand All @@ -69,6 +70,7 @@ void WorkerThreadPool::_process_task(Task *p_task) {
curr_thread.current_task = p_task;
task_mutex.unlock();
}
#endif
adamscott marked this conversation as resolved.
Show resolved Hide resolved

if (p_task->group) {
// Handling a group
Expand Down Expand Up @@ -143,6 +145,7 @@ void WorkerThreadPool::_process_task(Task *p_task) {
}
}

#ifdef THREADS_ENABLED
{
curr_thread.current_task = prev_task;
if (p_task->low_priority) {
Expand All @@ -159,6 +162,7 @@ void WorkerThreadPool::_process_task(Task *p_task) {
}

set_current_thread_safe_for_nodes(safe_for_nodes_backup);
#endif
adamscott marked this conversation as resolved.
Show resolved Hide resolved
}

void WorkerThreadPool::_thread_function(void *p_user) {
Expand Down Expand Up @@ -542,6 +546,7 @@ bool WorkerThreadPool::is_group_task_completed(GroupID p_group) const {
}

void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) {
#ifdef THREADS_ENABLED
task_mutex.lock();
Group **groupp = groups.getptr(p_group);
task_mutex.unlock();
Expand Down Expand Up @@ -574,6 +579,7 @@ void WorkerThreadPool::wait_for_group_task_completion(GroupID p_group) {
task_mutex.lock(); // This mutex is needed when Physics 2D and/or 3D is selected to run on a separate thread.
groups.erase(p_group);
task_mutex.unlock();
#endif
}

int WorkerThreadPool::get_thread_index() {
Expand Down
14 changes: 14 additions & 0 deletions core/os/condition_variable.h
adamscott marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@

#include "core/os/mutex.h"

#ifdef THREADS_ENABLED

#ifdef MINGW_ENABLED
#define MINGW_STDTHREAD_REDUNDANCY_WARNING
#include "thirdparty/mingw-std-threads/mingw.condition_variable.h"
Expand Down Expand Up @@ -66,4 +68,16 @@ class ConditionVariable {
}
};

#else // No threads.

class ConditionVariable {
public:
template <class BinaryMutexT>
void wait(const MutexLock<BinaryMutexT> &p_lock) const {}
void notify_one() const {}
void notify_all() const {}
};

#endif // THREADS_ENABLED

#endif // CONDITION_VARIABLE_H
4 changes: 4 additions & 0 deletions core/os/mutex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ void _global_unlock() {
_global_mutex.unlock();
}

#ifdef THREADS_ENABLED

template class MutexImpl<THREADING_NAMESPACE::recursive_mutex>;
template class MutexImpl<THREADING_NAMESPACE::mutex>;
template class MutexLock<MutexImpl<THREADING_NAMESPACE::recursive_mutex>>;
template class MutexLock<MutexImpl<THREADING_NAMESPACE::mutex>>;

#endif
40 changes: 38 additions & 2 deletions core/os/mutex.h
adamscott marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#define THREADING_NAMESPACE std
#endif

#ifdef THREADS_ENABLED

template <class MutexT>
class MutexLock;

Expand Down Expand Up @@ -125,8 +127,8 @@ class MutexLock {
THREADING_NAMESPACE::unique_lock<typename MutexT::StdMutexType> lock;

public:
_ALWAYS_INLINE_ explicit MutexLock(const MutexT &p_mutex) :
lock(p_mutex.mutex){};
explicit MutexLock(const MutexT &p_mutex) :
lock(p_mutex.mutex) {}
};

// This specialization is needed so manual locking and MutexLock can be used
Expand Down Expand Up @@ -155,4 +157,38 @@ extern template class MutexImpl<THREADING_NAMESPACE::mutex>;
extern template class MutexLock<MutexImpl<THREADING_NAMESPACE::recursive_mutex>>;
extern template class MutexLock<MutexImpl<THREADING_NAMESPACE::mutex>>;

#else // No threads.

class MutexImpl {
mutable THREADING_NAMESPACE::mutex mutex;

public:
void lock() const {}
void unlock() const {}
bool try_lock() const { return true; }
};

template <int Tag>
class SafeBinaryMutex : public MutexImpl {
static thread_local uint32_t count;
};

template <class MutexT>
class MutexLock {
public:
MutexLock(const MutexT &p_mutex) {}
};

template <int Tag>
class MutexLock<SafeBinaryMutex<Tag>> {
public:
MutexLock(const SafeBinaryMutex<Tag> &p_mutex) {}
~MutexLock() {}
};

using Mutex = MutexImpl;
using BinaryMutex = MutexImpl;

#endif // THREADS_ENABLED

#endif // MUTEX_H
6 changes: 6 additions & 0 deletions core/os/os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,12 @@ bool OS::has_feature(const String &p_feature) {
}
#endif

#ifdef THREADS_ENABLED
if (p_feature == "threads") {
return true;
}
#endif

if (_check_internal_feature_support(p_feature)) {
return true;
}
Expand Down
17 changes: 17 additions & 0 deletions core/os/semaphore.h
adamscott marked this conversation as resolved.
Show resolved Hide resolved
adamscott marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
#ifndef SEMAPHORE_H
#define SEMAPHORE_H

#include <cstdint>

#ifdef THREADS_ENABLED

#include "core/error/error_list.h"
#include "core/typedefs.h"
#ifdef DEBUG_ENABLED
Expand Down Expand Up @@ -132,4 +136,17 @@ class Semaphore {
#endif
};

#else // No threads.

class Semaphore {
public:
void post(uint32_t p_count = 1) const {}
void wait() const {}
bool try_wait() const {
return true;
}
};

#endif // THREADS_ENABLED

#endif // SEMAPHORE_H
9 changes: 7 additions & 2 deletions core/os/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,22 @@

#include "thread.h"

#ifdef THREADS_ENABLED
#include "core/object/script_language.h"
#include "core/templates/safe_refcount.h"

Thread::PlatformFunctions Thread::platform_functions;

SafeNumeric<uint64_t> Thread::id_counter(1); // The first value after .increment() is 2, hence by default the main thread ID should be 1.

thread_local Thread::ID Thread::caller_id = Thread::UNASSIGNED_ID;
#endif

Thread::PlatformFunctions Thread::platform_functions;

void Thread::_set_platform_functions(const PlatformFunctions &p_functions) {
platform_functions = p_functions;
}

#ifdef THREADS_ENABLED
void Thread::callback(ID p_caller_id, const Settings &p_settings, Callback p_callback, void *p_userdata) {
Thread::caller_id = p_caller_id;
if (platform_functions.set_priority) {
Expand Down Expand Up @@ -107,4 +110,6 @@ Thread::~Thread() {
}
}

#endif // THREADS_ENABLED

#endif // PLATFORM_THREAD_OVERRIDE
64 changes: 62 additions & 2 deletions core/os/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@

class String;

#ifdef THREADS_ENABLED

class Thread {
public:
typedef void (*Callback)(void *p_userdata);
Expand Down Expand Up @@ -86,15 +88,15 @@ class Thread {
private:
friend class Main;

static PlatformFunctions platform_functions;

ID id = UNASSIGNED_ID;
static SafeNumeric<uint64_t> id_counter;
static thread_local ID caller_id;
THREADING_NAMESPACE::thread thread;

static void callback(ID p_caller_id, const Settings &p_settings, Thread::Callback p_callback, void *p_userdata);

static PlatformFunctions platform_functions;

static void make_main_thread() { caller_id = MAIN_ID; }
static void release_main_thread() { caller_id = UNASSIGNED_ID; }

Expand Down Expand Up @@ -125,6 +127,64 @@ class Thread {
~Thread();
};

#else // No threads.

class Thread {
public:
typedef void (*Callback)(void *p_userdata);

typedef uint64_t ID;

enum : ID {
UNASSIGNED_ID = 0,
MAIN_ID = 1
};

enum Priority {
PRIORITY_LOW,
PRIORITY_NORMAL,
PRIORITY_HIGH
};

struct Settings {
Priority priority;
Settings() { priority = PRIORITY_NORMAL; }
};

struct PlatformFunctions {
Error (*set_name)(const String &) = nullptr;
void (*set_priority)(Thread::Priority) = nullptr;
void (*init)() = nullptr;
void (*wrapper)(Thread::Callback, void *) = nullptr;
void (*term)() = nullptr;
};

private:
friend class Main;

static PlatformFunctions platform_functions;

static void make_main_thread() {}
static void release_main_thread() {}

public:
static void _set_platform_functions(const PlatformFunctions &p_functions);

_FORCE_INLINE_ ID get_id() const { return 0; }
_FORCE_INLINE_ static ID get_caller_id() { return MAIN_ID; }
_FORCE_INLINE_ static ID get_main_id() { return MAIN_ID; }

_FORCE_INLINE_ static bool is_main_thread() { return true; }

static Error set_name(const String &p_name) { return ERR_UNAVAILABLE; }

void start(Thread::Callback p_callback, void *p_user, const Settings &p_settings = Settings()) {}
bool is_started() const { return false; }
void wait_to_finish() {}
};

#endif // THREADS_ENABLED

#endif // THREAD_H

#endif // PLATFORM_THREAD_OVERRIDE
Loading
Loading