summaryrefslogtreecommitdiff
path: root/core/object/object.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/object/object.cpp')
-rw-r--r--core/object/object.cpp98
1 files changed, 62 insertions, 36 deletions
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 00b89ab398..0644012318 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -386,12 +386,20 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid
}
if (_extension && _extension->set) {
- if (_extension->set(_extension_instance, &p_name, &p_value)) {
+// C style pointer casts should never trigger a compiler warning because the risk is assumed by the user, so GCC should keep quiet about it.
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wignored-qualifiers"
+#endif
+ if (_extension->set(_extension_instance, (const GDNativeStringNamePtr)&p_name, (const GDNativeVariantPtr)&p_value)) {
if (r_valid) {
*r_valid = true;
}
return;
}
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
}
//try built-in setgetter
@@ -459,14 +467,22 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const {
return ret;
}
}
-
if (_extension && _extension->get) {
- if (_extension->get(_extension_instance, &p_name, &ret)) {
+// C style pointer casts should never trigger a compiler warning because the risk is assumed by the user, so GCC should keep quiet about it.
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wignored-qualifiers"
+#endif
+
+ if (_extension->get(_extension_instance, (const GDNativeStringNamePtr)&p_name, (GDNativeVariantPtr)&ret)) {
if (r_valid) {
*r_valid = true;
}
return ret;
}
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
}
//try built-in setgetter
@@ -616,7 +632,7 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
if (_extension && _extension->get_property_list) {
uint32_t pcount;
- const ObjectNativeExtension::PInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount);
+ const GDNativePropertyInfo *pinfo = _extension->get_property_list(_extension_instance, &pcount);
for (uint32_t i = 0; i < pcount; i++) {
p_list->push_back(PropertyInfo(Variant::Type(pinfo[i].type), pinfo[i].class_name, PropertyHint(pinfo[i].hint), pinfo[i].hint_string, pinfo[i].usage, pinfo[i].class_name));
}
@@ -1753,42 +1769,52 @@ uint32_t Object::get_edited_version() const {
}
#endif
-void *Object::get_script_instance_binding(int p_script_language_index) {
-#ifdef DEBUG_ENABLED
- ERR_FAIL_INDEX_V(p_script_language_index, MAX_SCRIPT_INSTANCE_BINDINGS, nullptr);
-#endif
-
- //it's up to the script language to make this thread safe, if the function is called twice due to threads being out of sync
- //just return the same pointer.
- //if you want to put a big lock in the entire function and keep allocated pointers in a map or something, feel free to do it
- //as it should not really affect performance much (won't be called too often), as in far most cases the condition below will be false afterwards
-
- if (!_script_instance_bindings[p_script_language_index]) {
- void *script_data = ScriptServer::get_language(p_script_language_index)->alloc_instance_binding_data(this);
- if (script_data) {
- instance_binding_count.increment();
- _script_instance_bindings[p_script_language_index] = script_data;
+void Object::set_instance_binding(void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks) {
+ // This is only meant to be used on creation by the binder.
+ ERR_FAIL_COND(_instance_bindings != nullptr);
+ _instance_bindings = (InstanceBinding *)memalloc(sizeof(InstanceBinding));
+ _instance_bindings[0].binding = p_binding;
+ _instance_bindings[0].free_callback = p_callbacks->free_callback;
+ _instance_bindings[0].reference_callback = p_callbacks->reference_callback;
+ _instance_bindings[0].token = p_token;
+ _instance_binding_count = 1;
+}
+
+void *Object::get_instance_binding(void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks) {
+ void *binding = nullptr;
+ _instance_binding_mutex.lock();
+ for (uint32_t i = 0; i < _instance_binding_count; i++) {
+ if (_instance_bindings[i].token == p_token) {
+ binding = _instance_bindings[i].binding;
+ break;
}
}
+ if (unlikely(!binding)) {
+ uint32_t current_size = next_power_of_2(_instance_binding_count);
+ uint32_t new_size = next_power_of_2(_instance_binding_count + 1);
- return _script_instance_bindings[p_script_language_index];
-}
+ if (current_size == 0 || new_size > current_size) {
+ _instance_bindings = (InstanceBinding *)memrealloc(_instance_bindings, new_size * sizeof(InstanceBinding));
+ }
-bool Object::has_script_instance_binding(int p_script_language_index) {
- return _script_instance_bindings[p_script_language_index] != nullptr;
-}
+ _instance_bindings[_instance_binding_count].free_callback = p_callbacks->free_callback;
+ _instance_bindings[_instance_binding_count].reference_callback = p_callbacks->reference_callback;
+ _instance_bindings[_instance_binding_count].token = p_token;
-void Object::set_script_instance_binding(int p_script_language_index, void *p_data) {
-#ifdef DEBUG_ENABLED
- CRASH_COND(_script_instance_bindings[p_script_language_index] != nullptr);
-#endif
- _script_instance_bindings[p_script_language_index] = p_data;
+ binding = p_callbacks->create_callback(p_token, this);
+ _instance_bindings[_instance_binding_count].binding = binding;
+
+ _instance_binding_count++;
+ }
+
+ _instance_binding_mutex.unlock();
+
+ return binding;
}
void Object::_construct_object(bool p_reference) {
type_is_reference = p_reference;
_instance_id = ObjectDB::add_instance(this);
- memset(_script_instance_bindings, 0, sizeof(void *) * MAX_SCRIPT_INSTANCE_BINDINGS);
ClassDB::instance_get_native_extension_data(&_extension, &_extension_instance);
@@ -1812,7 +1838,7 @@ Object::~Object() {
script_instance = nullptr;
if (_extension && _extension->free_instance) {
- _extension->free_instance(_extension->create_instance_userdata, _extension_instance);
+ _extension->free_instance(_extension->class_userdata, _extension_instance);
_extension = nullptr;
_extension_instance = nullptr;
}
@@ -1848,12 +1874,13 @@ Object::~Object() {
_instance_id = ObjectID();
_predelete_ok = 2;
- if (!ScriptServer::are_languages_finished()) {
- for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
- if (_script_instance_bindings[i]) {
- ScriptServer::get_language(i)->free_instance_binding_data(_script_instance_bindings[i]);
+ if (_instance_bindings != nullptr) {
+ for (uint32_t i = 0; i < _instance_binding_count; i++) {
+ if (_instance_bindings[i].free_callback) {
+ _instance_bindings[i].free_callback(_instance_bindings[i].token, _instance_bindings[i].binding, this);
}
}
+ memfree(_instance_bindings);
}
}
@@ -1871,7 +1898,6 @@ void ObjectDB::debug_objects(DebugFunc p_func) {
for (uint32_t i = 0, count = slot_count; i < slot_max && count != 0; i++) {
if (object_slots[i].validator) {
p_func(object_slots[i].object);
-
count--;
}
}