Skip to content

Commit ca5179f

Browse files
authored
Merge pull request #1594 from dsnopek/macos-thread-local
Avoid `thread_local` on MacOS to prevent issues with hot reload
2 parents fa3dfa0 + 91833c8 commit ca5179f

File tree

3 files changed

+33
-6
lines changed

3 files changed

+33
-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,11 +66,15 @@ 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>
@@ -121,6 +133,9 @@ class Wrapped {
121133

122134
template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>>
123135
_ALWAYS_INLINE_ void _pre_initialize() {
136+
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
137+
Wrapped::_constructing_mutex.lock();
138+
#endif
124139
Wrapped::_set_construct_info<T>();
125140
}
126141

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: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,27 @@
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() {
5055
return nullptr;
5156
}
5257

5358
void Wrapped::_postinitialize() {
59+
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
60+
Wrapped::_constructing_mutex.unlock();
61+
#endif
62+
5463
// Only send NOTIFICATION_POSTINITIALIZE for extension classes.
5564
if (_is_extension_class()) {
5665
_notificationv(Object::NOTIFICATION_POSTINITIALIZE);

0 commit comments

Comments
 (0)