Skip to content

Commit

Permalink
Avoid thread_local on MacOS to prevent issues with hot reload
Browse files Browse the repository at this point in the history
  • Loading branch information
dsnopek committed Oct 17, 2024
1 parent a98d41f commit 91833c8
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 6 deletions.
21 changes: 18 additions & 3 deletions include/godot_cpp/classes/wrapped.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@

#include <godot_cpp/godot.hpp>

#if defined(MACOS_ENABLED) && defined(HOT_RELOAD_ENABLED)
#include <mutex>
#define _GODOT_CPP_AVOID_THREAD_LOCAL
#define _GODOT_CPP_THREAD_LOCAL
#else
#define _GODOT_CPP_THREAD_LOCAL thread_local
#endif

namespace godot {

class ClassDB;
Expand All @@ -58,11 +66,15 @@ class Wrapped {
template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>>
friend _ALWAYS_INLINE_ void _pre_initialize();

thread_local static const StringName *_constructing_extension_class_name;
thread_local static const GDExtensionInstanceBindingCallbacks *_constructing_class_binding_callbacks;
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
static std::recursive_mutex _constructing_mutex;
#endif

_GODOT_CPP_THREAD_LOCAL static const StringName *_constructing_extension_class_name;
_GODOT_CPP_THREAD_LOCAL static const GDExtensionInstanceBindingCallbacks *_constructing_class_binding_callbacks;

#ifdef HOT_RELOAD_ENABLED
thread_local static GDExtensionObjectPtr _constructing_recreate_owner;
_GODOT_CPP_THREAD_LOCAL static GDExtensionObjectPtr _constructing_recreate_owner;
#endif

template <typename T>
Expand Down Expand Up @@ -121,6 +133,9 @@ class Wrapped {

template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>>
_ALWAYS_INLINE_ void _pre_initialize() {
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
Wrapped::_constructing_mutex.lock();
#endif
Wrapped::_set_construct_info<T>();
}

Expand Down
3 changes: 3 additions & 0 deletions include/godot_cpp/core/class_db.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ class ClassDB {
static GDExtensionClassInstancePtr _recreate_instance_func(void *data, GDExtensionObjectPtr obj) {
if constexpr (!std::is_abstract_v<T>) {
#ifdef HOT_RELOAD_ENABLED
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
std::lock_guard<std::recursive_mutex> lk(Wrapped::_constructing_mutex);
#endif
Wrapped::_constructing_recreate_owner = obj;
T *new_instance = (T *)memalloc(sizeof(T));
memnew_placement(new_instance, T);
Expand Down
15 changes: 12 additions & 3 deletions src/classes/wrapped.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,27 @@
#include <godot_cpp/core/class_db.hpp>

namespace godot {
thread_local const StringName *Wrapped::_constructing_extension_class_name = nullptr;
thread_local const GDExtensionInstanceBindingCallbacks *Wrapped::_constructing_class_binding_callbacks = nullptr;

#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
std::recursive_mutex Wrapped::_constructing_mutex;
#endif

_GODOT_CPP_THREAD_LOCAL const StringName *Wrapped::_constructing_extension_class_name = nullptr;
_GODOT_CPP_THREAD_LOCAL const GDExtensionInstanceBindingCallbacks *Wrapped::_constructing_class_binding_callbacks = nullptr;

#ifdef HOT_RELOAD_ENABLED
thread_local GDExtensionObjectPtr Wrapped::_constructing_recreate_owner = nullptr;
_GODOT_CPP_THREAD_LOCAL GDExtensionObjectPtr Wrapped::_constructing_recreate_owner = nullptr;
#endif

const StringName *Wrapped::_get_extension_class_name() {
return nullptr;
}

void Wrapped::_postinitialize() {
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
Wrapped::_constructing_mutex.unlock();
#endif

// Only send NOTIFICATION_POSTINITIALIZE for extension classes.
if (_is_extension_class()) {
_notificationv(Object::NOTIFICATION_POSTINITIALIZE);
Expand Down

0 comments on commit 91833c8

Please sign in to comment.