Merge pull request #1594 from dsnopek/macos-thread-local

Avoid `thread_local` on MacOS to prevent issues with hot reload
pull/1568/head
David Snopek 2024-10-29 15:39:49 -05:00 committed by GitHub
commit ca5179f7d7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 33 additions and 6 deletions

View File

@ -40,6 +40,14 @@
#include <godot_cpp/godot.hpp> #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 { namespace godot {
class ClassDB; class ClassDB;
@ -58,11 +66,15 @@ class Wrapped {
template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>> template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>>
friend _ALWAYS_INLINE_ void _pre_initialize(); friend _ALWAYS_INLINE_ void _pre_initialize();
thread_local static const StringName *_constructing_extension_class_name; #ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
thread_local static const GDExtensionInstanceBindingCallbacks *_constructing_class_binding_callbacks; 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 #ifdef HOT_RELOAD_ENABLED
thread_local static GDExtensionObjectPtr _constructing_recreate_owner; _GODOT_CPP_THREAD_LOCAL static GDExtensionObjectPtr _constructing_recreate_owner;
#endif #endif
template <typename T> template <typename T>
@ -121,6 +133,9 @@ public:
template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>> template <typename T, std::enable_if_t<std::is_base_of<::godot::Wrapped, T>::value, bool>>
_ALWAYS_INLINE_ void _pre_initialize() { _ALWAYS_INLINE_ void _pre_initialize() {
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
Wrapped::_constructing_mutex.lock();
#endif
Wrapped::_set_construct_info<T>(); Wrapped::_set_construct_info<T>();
} }

View File

@ -129,6 +129,9 @@ private:
static GDExtensionClassInstancePtr _recreate_instance_func(void *data, GDExtensionObjectPtr obj) { static GDExtensionClassInstancePtr _recreate_instance_func(void *data, GDExtensionObjectPtr obj) {
if constexpr (!std::is_abstract_v<T>) { if constexpr (!std::is_abstract_v<T>) {
#ifdef HOT_RELOAD_ENABLED #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; Wrapped::_constructing_recreate_owner = obj;
T *new_instance = (T *)memalloc(sizeof(T)); T *new_instance = (T *)memalloc(sizeof(T));
memnew_placement(new_instance, T); memnew_placement(new_instance, T);

View File

@ -39,11 +39,16 @@
#include <godot_cpp/core/class_db.hpp> #include <godot_cpp/core/class_db.hpp>
namespace godot { 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 #ifdef HOT_RELOAD_ENABLED
thread_local GDExtensionObjectPtr Wrapped::_constructing_recreate_owner = nullptr; _GODOT_CPP_THREAD_LOCAL GDExtensionObjectPtr Wrapped::_constructing_recreate_owner = nullptr;
#endif #endif
const StringName *Wrapped::_get_extension_class_name() { const StringName *Wrapped::_get_extension_class_name() {
@ -51,6 +56,10 @@ const StringName *Wrapped::_get_extension_class_name() {
} }
void Wrapped::_postinitialize() { void Wrapped::_postinitialize() {
#ifdef _GODOT_CPP_AVOID_THREAD_LOCAL
Wrapped::_constructing_mutex.unlock();
#endif
// Only send NOTIFICATION_POSTINITIALIZE for extension classes. // Only send NOTIFICATION_POSTINITIALIZE for extension classes.
if (_is_extension_class()) { if (_is_extension_class()) {
_notificationv(Object::NOTIFICATION_POSTINITIALIZE); _notificationv(Object::NOTIFICATION_POSTINITIALIZE);