Skip to content

Commit cdea1ad

Browse files
committed
Avoid thread_local on MacOS to prevent issues with hot reload
1 parent cb543c1 commit cdea1ad

File tree

3 files changed

+29
-6
lines changed

3 files changed

+29
-6
lines changed

include/godot_cpp/classes/wrapped.hpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@
4040

4141
#include <godot_cpp/godot.hpp>
4242

43+
#if defined(MACOS_ENABLED) && defined(HOT_RELOAD_ENABLED)
44+
#include <mutex>
45+
#define _GODOT_CPP_AVOID_THREAD_LOCAL
46+
#define _GODOT_CPP_THREAD_LOCAL
47+
#else
48+
#define _GODOT_CPP_THREAD_LOCAL thread_local
49+
#endif
50+
4351
namespace godot {
4452

4553
class ClassDB;
@@ -58,15 +66,22 @@ class Wrapped {
5866
template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>>
5967
friend _ALWAYS_INLINE_ void _pre_initialize();
6068

61-
thread_local static const StringName *_constructing_extension_class_name;
62-
thread_local static const GDExtensionInstanceBindingCallbacks *_constructing_class_binding_callbacks;
69+
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
70+
static std::recursive_mutex _constructing_mutex;
71+
#endif
72+
73+
_GODOT_CPP_THREAD_LOCAL static const StringName *_constructing_extension_class_name;
74+
_GODOT_CPP_THREAD_LOCAL static const GDExtensionInstanceBindingCallbacks *_constructing_class_binding_callbacks;
6375

6476
#ifdef HOT_RELOAD_ENABLED
65-
thread_local static GDExtensionObjectPtr _constructing_recreate_owner;
77+
_GODOT_CPP_THREAD_LOCAL static GDExtensionObjectPtr _constructing_recreate_owner;
6678
#endif
6779

6880
template <typename T>
6981
_ALWAYS_INLINE_ static void _set_construct_info() {
82+
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
83+
std::lock_guard<std::recursive_mutex> lk(Wrapped::_constructing_mutex);
84+
#endif
7085
_constructing_extension_class_name = T::_get_extension_class_name();
7186
_constructing_class_binding_callbacks = &T::_gde_binding_callbacks;
7287
}

include/godot_cpp/core/class_db.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ class ClassDB {
129129
static GDExtensionClassInstancePtr _recreate_instance_func(void *data, GDExtensionObjectPtr obj) {
130130
if constexpr (!std::is_abstract_v<T>) {
131131
#ifdef HOT_RELOAD_ENABLED
132+
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
133+
std::lock_guard<std::recursive_mutex> lk(Wrapped::_constructing_mutex);
134+
#endif
132135
Wrapped::_constructing_recreate_owner = obj;
133136
T *new_instance = (T *)memalloc(sizeof(T));
134137
memnew_placement(new_instance, T);

src/classes/wrapped.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,16 @@
3939
#include <godot_cpp/core/class_db.hpp>
4040

4141
namespace godot {
42-
thread_local const StringName *Wrapped::_constructing_extension_class_name = nullptr;
43-
thread_local const GDExtensionInstanceBindingCallbacks *Wrapped::_constructing_class_binding_callbacks = nullptr;
42+
43+
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
44+
std::recursive_mutex Wrapped::_constructing_mutex;
45+
#endif
46+
47+
_GODOT_CPP_THREAD_LOCAL const StringName *Wrapped::_constructing_extension_class_name = nullptr;
48+
_GODOT_CPP_THREAD_LOCAL const GDExtensionInstanceBindingCallbacks *Wrapped::_constructing_class_binding_callbacks = nullptr;
4449

4550
#ifdef HOT_RELOAD_ENABLED
46-
thread_local GDExtensionObjectPtr Wrapped::_constructing_recreate_owner = nullptr;
51+
_GODOT_CPP_THREAD_LOCAL GDExtensionObjectPtr Wrapped::_constructing_recreate_owner = nullptr;
4752
#endif
4853

4954
const StringName *Wrapped::_get_extension_class_name() {

0 commit comments

Comments
 (0)