From 533dadacef0c8a4fb6ef6d7db6cff3a0a977d211 Mon Sep 17 00:00:00 2001 From: Relintai Date: Sun, 31 Dec 2023 15:46:34 +0100 Subject: [PATCH] Variant cleanups. --- sfw/object/array.cpp | 8 ++-- sfw/object/dictionary.h | 6 +-- sfw/object/object_id.h | 13 ++++++ sfw/object/object_rc.h | 52 ++++++++++++++++++++++ sfw/object/ref_ptr.cpp | 97 +++++++++++++++++++++++++++++++++++++++++ sfw/object/ref_ptr.h | 36 +++++++++++++++ sfw/object/variant.cpp | 17 ++++---- sfw/object/variant.h | 92 +++++++++----------------------------- 8 files changed, 234 insertions(+), 87 deletions(-) create mode 100644 sfw/object/object_id.h create mode 100644 sfw/object/object_rc.h create mode 100644 sfw/object/ref_ptr.cpp create mode 100644 sfw/object/ref_ptr.h diff --git a/sfw/object/array.cpp b/sfw/object/array.cpp index cec04af..7408e09 100644 --- a/sfw/object/array.cpp +++ b/sfw/object/array.cpp @@ -5,10 +5,10 @@ #include "array.h" -#include "core/containers/hashfuncs.h" -#include "core/containers/vector.h" -#include "core/object/object.h" -#include "core/variant/variant.h" +#include "core/hashfuncs.h" +#include "core/vector.h" +#include "object/object.h" +#include "object/variant.h" class ArrayPrivate { public: diff --git a/sfw/object/dictionary.h b/sfw/object/dictionary.h index 16183d8..10762b7 100644 --- a/sfw/object/dictionary.h +++ b/sfw/object/dictionary.h @@ -6,9 +6,9 @@ /* From https://github.com/Relintai/pandemonium_engine (MIT) */ /*************************************************************************/ -#include "core/containers/list.h" -#include "core/string/ustring.h" -#include "core/variant/array.h" +#include "core/list.h" +#include "core/ustring.h" +#include "object/array.h" class Variant; diff --git a/sfw/object/object_id.h b/sfw/object/object_id.h new file mode 100644 index 0000000..a5ec4e8 --- /dev/null +++ b/sfw/object/object_id.h @@ -0,0 +1,13 @@ +#ifndef OBJECTID_H +#define OBJECTID_H + +/*************************************************************************/ +/* object_id.h */ +/* From https://github.com/Relintai/pandemonium_engine (MIT) */ +/*************************************************************************/ + +#include "core/int_types.h" + +typedef uint64_t ObjectID; + +#endif diff --git a/sfw/object/object_rc.h b/sfw/object/object_rc.h new file mode 100644 index 0000000..cee9339 --- /dev/null +++ b/sfw/object/object_rc.h @@ -0,0 +1,52 @@ +#ifndef OBJECTRC_H +#define OBJECTRC_H + +/*************************************************************************/ +/* object_rc.h */ +/* From https://github.com/Relintai/pandemonium_engine (MIT) */ +/*************************************************************************/ + +#include "core/memory.h" +#include "core/typedefs.h" + +#include + +class Object; + +// Used to track Variants pointing to a non-Reference Object +class ObjectRC { + std::atomic _ptr; + std::atomic _users; + +public: + // This is for allowing debug builds to check for instance ID validity, + // so warnings are shown in debug builds when a stray Variant (one pointing + // to a released Object) would have happened. + const ObjectID instance_id; + + _FORCE_INLINE_ void increment() { + _users.fetch_add(1, std::memory_order_relaxed); + } + + _FORCE_INLINE_ bool decrement() { + return _users.fetch_sub(1, std::memory_order_relaxed) == 1; + } + + _FORCE_INLINE_ bool invalidate() { + _ptr.store(nullptr, std::memory_order_release); + return decrement(); + } + + _FORCE_INLINE_ Object *get_ptr() { + return _ptr.load(std::memory_order_acquire); + } + + _FORCE_INLINE_ ObjectRC(Object *p_object) : + instance_id(p_object->get_instance_id()) { + // 1 (the Object) + 1 (the first user) + _users.store(2, std::memory_order_relaxed); + _ptr.store(p_object, std::memory_order_release); + } +}; + +#endif diff --git a/sfw/object/ref_ptr.cpp b/sfw/object/ref_ptr.cpp new file mode 100644 index 0000000..0ea1e21 --- /dev/null +++ b/sfw/object/ref_ptr.cpp @@ -0,0 +1,97 @@ +/*************************************************************************/ +/* ref_ptr.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* PANDEMONIUM ENGINE */ +/* https://github.com/Relintai/pandemonium_engine */ +/*************************************************************************/ +/* Copyright (c) 2022-present Péter Magyar. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "ref_ptr.h" + +#include "object/reference.h" +#include "object/resource.h" + +void RefPtr::operator=(const RefPtr &p_other) { + Ref *ref = reinterpret_cast *>(&data[0]); + Ref *ref_other = reinterpret_cast *>(const_cast(&p_other.data[0])); + + *ref = *ref_other; +} + +bool RefPtr::operator==(const RefPtr &p_other) const { + Ref *ref = reinterpret_cast *>(&data[0]); + Ref *ref_other = reinterpret_cast *>(const_cast(&p_other.data[0])); + + return *ref == *ref_other; +} + +bool RefPtr::operator!=(const RefPtr &p_other) const { + Ref *ref = reinterpret_cast *>(&data[0]); + Ref *ref_other = reinterpret_cast *>(const_cast(&p_other.data[0])); + + return *ref != *ref_other; +} + +RefPtr::RefPtr(const RefPtr &p_other) { + memnew_placement(&data[0], Ref); + + Ref *ref = reinterpret_cast *>(&data[0]); + Ref *ref_other = reinterpret_cast *>(const_cast(&p_other.data[0])); + + *ref = *ref_other; +} + +bool RefPtr::is_null() const { + Ref *ref = reinterpret_cast *>(&data[0]); + return ref->is_null(); +} + +RID RefPtr::get_rid() const { + Ref *ref = reinterpret_cast *>(&data[0]); + if (ref->is_null()) { + return RID(); + } + Resource *res = Object::cast_to(ref->ptr()); + if (res) { + return res->get_rid(); + } + return RID(); +} + +void RefPtr::unref() { + Ref *ref = reinterpret_cast *>(&data[0]); + ref->unref(); +} + +RefPtr::RefPtr() { + ERR_FAIL_COND(sizeof(Ref) > DATASIZE); + memnew_placement(&data[0], Ref); +} + +RefPtr::~RefPtr() { + Ref *ref = reinterpret_cast *>(&data[0]); + ref->~Ref(); +} diff --git a/sfw/object/ref_ptr.h b/sfw/object/ref_ptr.h new file mode 100644 index 0000000..8d0ee7a --- /dev/null +++ b/sfw/object/ref_ptr.h @@ -0,0 +1,36 @@ +#ifndef REF_PTR_H +#define REF_PTR_H + +/*************************************************************************/ +/* ref_ptr.h */ +/* From https://github.com/Relintai/pandemonium_engine (MIT) */ +/*************************************************************************/ + +/** + @author Juan Linietsky + * This class exists to workaround a limitation in C++ but keep the design OK. + * It's basically an opaque container of a Reference reference, so Variant can use it. +*/ + +#include "core/typedefs.h" + +class RefPtr { + enum { + DATASIZE = sizeof(void *) //*4 -ref was shrunk + }; + + mutable char data[DATASIZE]; // too much probably, virtual class + pointer +public: + bool is_null() const; + void operator=(const RefPtr &p_other); + bool operator==(const RefPtr &p_other) const; + bool operator!=(const RefPtr &p_other) const; + void unref(); + + _FORCE_INLINE_ void *get_data() const { return data; } + RefPtr(const RefPtr &p_other); + RefPtr(); + ~RefPtr(); +}; + +#endif // REF_PTR_H diff --git a/sfw/object/variant.cpp b/sfw/object/variant.cpp index 8ba3bf0..c4a9063 100644 --- a/sfw/object/variant.cpp +++ b/sfw/object/variant.cpp @@ -5,15 +5,14 @@ #include "variant.h" -#include "core/core_string_names.h" -#include "core/io/marshalls.h" -#include "core/math/math_funcs.h" -#include "core/object/object_rc.h" -#include "core/object/resource.h" -#include "core/string/print_string.h" -#include "core/variant/variant_parser.h" -#include "scene/main/control.h" -#include "scene/main/node.h" +//#include "core/core_string_names.h" +//#include "core/io/marshalls.h" + +#include "core/math_funcs.h" + +#include "object/object_rc.h" +#include "object/resource.h" + String Variant::get_type_name(Variant::Type p_type) { switch (p_type) { diff --git a/sfw/object/variant.h b/sfw/object/variant.h index e9312c2..71a1cc9 100644 --- a/sfw/object/variant.h +++ b/sfw/object/variant.h @@ -6,31 +6,26 @@ /* From https://github.com/Relintai/pandemonium_engine (MIT) */ /*************************************************************************/ -#include "core/pool_vector.h" #include "core/aabb.h" #include "core/basis.h" #include "core/color.h" -#include "face3.h" +#include "core/face3.h" #include "core/plane.h" +#include "core/pool_vector.h" #include "core/projection.h" #include "core/quaternion.h" #include "core/transform.h" #include "core/transform_2d.h" +#include "core/ustring.h" #include "core/vector3.h" #include "core/vector3i.h" #include "core/vector4.h" #include "core/vector4i.h" -#include "core/ustring.h" -#include "array.h" -#include "dictionary.h" +#include "object/array.h" +#include "object/dictionary.h" class Object; class ObjectRC; -class Node; // helper -class Control; // helper - -struct PropertyInfo; -struct MethodInfo; typedef PoolVector PoolByteArray; typedef PoolVector PoolIntArray; @@ -72,42 +67,40 @@ public: STRING, // math types - RECT2, // 5 + RECT2, RECT2I, VECTOR2, VECTOR2I, VECTOR3, - VECTOR3I, // 10 + VECTOR3I, VECTOR4, VECTOR4I, PLANE, QUATERNION, - AABB, // 15 + AABB, BASIS, TRANSFORM, TRANSFORM2D, PROJECTION, // misc types - COLOR, // 20 - NODE_PATH, - RID, + COLOR, OBJECT, STRING_NAME, - DICTIONARY, // 25 + DICTIONARY, ARRAY, // arrays POOL_BYTE_ARRAY, POOL_INT_ARRAY, POOL_REAL_ARRAY, - POOL_STRING_ARRAY, //30 + POOL_STRING_ARRAY, POOL_VECTOR2_ARRAY, POOL_VECTOR2I_ARRAY, POOL_VECTOR3_ARRAY, POOL_VECTOR3I_ARRAY, - POOL_VECTOR4_ARRAY, //35 + POOL_VECTOR4_ARRAY, POOL_VECTOR4I_ARRAY, POOL_COLOR_ARRAY, @@ -121,7 +114,6 @@ public: }; private: - friend struct _VariantCall; // Variant takes 20 bytes when real_t is float, and 36 if double // it only allocates extra memory for aabb/matrix. @@ -209,12 +201,9 @@ public: operator Projection() const; operator Color() const; - operator NodePath() const; operator RefPtr() const; operator Object *() const; - operator Node *() const; - operator Control *() const; operator Dictionary() const; operator Array() const; @@ -328,7 +317,6 @@ public: // If this changes the table in variant_op must be updated enum Operator { - //comparison OP_EQUAL, OP_NOT_EQUAL, @@ -360,9 +348,14 @@ public: //containment OP_IN, OP_MAX - }; + //Maybe add helper methods that use these + //Like max() + //add() + //maybe operators like with add + //? + static String get_operator_name(Operator p_op); static void evaluate(const Operator &p_op, const Variant &p_a, const Variant &p_b, Variant &r_ret, bool &r_valid); static _FORCE_INLINE_ Variant evaluate(const Operator &p_op, const Variant &p_a, const Variant &p_b) { @@ -378,39 +371,12 @@ public: static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst); static void sub(const Variant &a, const Variant &b, Variant &r_dst); - struct CallError { - enum Error { - CALL_OK, - CALL_ERROR_INVALID_METHOD, - CALL_ERROR_INVALID_ARGUMENT, - CALL_ERROR_TOO_MANY_ARGUMENTS, - CALL_ERROR_TOO_FEW_ARGUMENTS, - CALL_ERROR_INSTANCE_IS_NULL, - }; - Error error; - int argument; - Type expected; - }; - - void call_ptr(const StringName &p_method, const Variant **p_args, int p_argcount, Variant *r_ret, CallError &r_error); - Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, CallError &r_error); - Variant call(const StringName &p_method, const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant(), const Variant &p_arg6 = Variant(), const Variant &p_arg7 = Variant(), const Variant &p_arg8 = Variant()); - - static String get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Variant::CallError &ce); - - static Variant construct(const Variant::Type, const Variant **p_args, int p_argcount, CallError &r_error, bool p_strict = true); - - void get_method_list(List *p_list) const; - bool has_method(const StringName &p_method) const; - static Vector get_method_argument_types(Variant::Type p_type, const StringName &p_method); - static Vector get_method_default_arguments(Variant::Type p_type, const StringName &p_method); - static Variant::Type get_method_return_type(Variant::Type p_type, const StringName &p_method, bool *r_has_return = nullptr); - static Vector get_method_argument_names(Variant::Type p_type, const StringName &p_method); - static bool is_method_const(Variant::Type p_type, const StringName &p_method); - + //Maybe add helper methods that call this? like get_x(), set_x() etc Or just x(), x(value)? + //Check if operator[] can take strings and ints that might work too void set_named(const StringName &p_index, const Variant &p_value, bool *r_valid = nullptr); Variant get_named(const StringName &p_index, bool *r_valid = nullptr) const; + //Implement operator[]s that use these? void set(const Variant &p_index, const Variant &p_value, bool *r_valid = nullptr); Variant get(const Variant &p_index, bool *r_valid = nullptr) const; bool in(const Variant &p_index, bool *r_valid = nullptr) const; @@ -419,10 +385,6 @@ public: bool iter_next(Variant &r_iter, bool &r_valid) const; Variant iter_get(const Variant &r_iter, bool &r_valid) const; - void get_property_list(List *p_list) const; - - //argsVariant call() - bool deep_equal(const Variant &p_variant, int p_recursion_count = 0) const; bool operator==(const Variant &p_variant) const; bool operator!=(const Variant &p_variant) const; @@ -434,18 +396,6 @@ public: bool booleanize() const; String stringify(List &stack) const; - void static_assign(const Variant &p_variant); - static void get_constructor_list(Variant::Type p_type, List *p_list); - static void get_constants_for_type(Variant::Type p_type, List *p_constants); - static bool has_constant(Variant::Type p_type, const StringName &p_value); - static Variant get_constant_value(Variant::Type p_type, const StringName &p_value, bool *r_valid = nullptr); - - typedef String (*ObjectDeConstruct)(const Variant &p_object, void *ud); - typedef void (*ObjectConstruct)(const String &p_text, void *ud, Variant &r_value); - - String get_construct_string() const; - static void construct_from_string(const String &p_string, Variant &r_value, ObjectConstruct p_obj_construct = nullptr, void *p_construct_ud = nullptr); - void operator=(const Variant &p_variant); // only this is enough for all the other types Variant(const Variant &p_variant); _FORCE_INLINE_ Variant() {