summaryrefslogtreecommitdiffstats
path: root/core/object.h
diff options
context:
space:
mode:
Diffstat (limited to 'core/object.h')
-rw-r--r--core/object.h133
1 files changed, 71 insertions, 62 deletions
diff --git a/core/object.h b/core/object.h
index 865c155764..59d3f06cfe 100644
--- a/core/object.h
+++ b/core/object.h
@@ -34,8 +34,10 @@
#include "core/hash_map.h"
#include "core/list.h"
#include "core/map.h"
+#include "core/object_id.h"
#include "core/os/rw_lock.h"
#include "core/set.h"
+#include "core/spin_lock.h"
#include "core/variant.h"
#include "core/vmap.h"
@@ -89,6 +91,7 @@ enum PropertyHint {
PROPERTY_HINT_OBJECT_TOO_BIG, ///< object is too big to send
PROPERTY_HINT_NODE_PATH_VALID_TYPES,
PROPERTY_HINT_SAVE_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,". This opens a save dialog
+ PROPERTY_HINT_INT_IS_OBJECTID,
PROPERTY_HINT_MAX,
// When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit
};
@@ -123,6 +126,7 @@ enum PropertyUsageFlags {
PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT = 1 << 23,
PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 24,
PROPERTY_USAGE_KEYING_INCREMENTS = 1 << 25, // Used in inspector to increment property when keyed in animation player
+ PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 26, // when loading, the resource for this property can be set at the end of loading
PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK,
PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED,
@@ -397,7 +401,6 @@ public: \
private:
class ScriptInstance;
-typedef uint64_t ObjectID;
class Object {
public:
@@ -411,18 +414,15 @@ public:
struct Connection {
- Object *source;
- StringName signal;
- Object *target;
- StringName method;
+ ::Signal signal;
+ Callable callable;
+
uint32_t flags;
Vector<Variant> binds;
bool operator<(const Connection &p_conn) const;
operator Variant() const;
Connection() {
- source = NULL;
- target = NULL;
flags = 0;
}
Connection(const Variant &p_variant);
@@ -439,21 +439,7 @@ private:
friend bool predelete_handler(Object *);
friend void postinitialize_handler(Object *);
- struct Signal {
-
- struct Target {
-
- ObjectID _id;
- StringName method;
-
- _FORCE_INLINE_ bool operator<(const Target &p_target) const { return (_id == p_target._id) ? (method < p_target.method) : (_id < p_target._id); }
-
- Target(const ObjectID &p_id, const StringName &p_method) :
- _id(p_id),
- method(p_method) {
- }
- Target() { _id = 0; }
- };
+ struct SignalData {
struct Slot {
@@ -464,11 +450,11 @@ private:
};
MethodInfo user;
- VMap<Target, Slot> slot_map;
- Signal() {}
+ VMap<Callable, Slot> slot_map;
+ SignalData() {}
};
- HashMap<StringName, Signal> signal_map;
+ HashMap<StringName, SignalData> signal_map;
List<Connection> connections;
#ifdef DEBUG_ENABLED
SafeRefCount _lock_index;
@@ -487,14 +473,14 @@ private:
Set<String> editor_section_folding;
#endif
ScriptInstance *script_instance;
- RefPtr script;
+ Variant script; //reference does not yet exist, store it in a
Dictionary metadata;
mutable StringName _class_name;
mutable const StringName *_class_ptr;
void _add_user_signal(const String &p_name, const Array &p_args = Array());
bool _has_user_signal(const StringName &p_name) const;
- Variant _emit_signal(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
+ Variant _emit_signal(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
Array _get_signal_list() const;
Array _get_signal_connection_list(const String &p_signal) const;
Array _get_incoming_connections() const;
@@ -505,9 +491,13 @@ private:
void property_list_changed_notify();
+ _FORCE_INLINE_ void _construct_object(bool p_reference);
+
friend class Reference;
+ bool type_is_reference = false;
uint32_t instance_binding_count;
void *_script_instance_bindings[MAX_SCRIPT_INSTANCE_BINDINGS];
+ Object(bool p_reference);
protected:
virtual void _initialize_classv() { initialize_class(); }
@@ -548,8 +538,8 @@ protected:
//Variant _call_bind(const StringName& p_name, const Variant& p_arg1 = Variant(), const Variant& p_arg2 = Variant(), const Variant& p_arg3 = Variant(), const Variant& p_arg4 = Variant());
//void _call_deferred_bind(const StringName& p_name, const Variant& p_arg1 = Variant(), const Variant& p_arg2 = Variant(), const Variant& p_arg3 = Variant(), const Variant& p_arg4 = Variant());
- Variant _call_bind(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
- Variant _call_deferred_bind(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
+ Variant _call_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ Variant _call_deferred_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
virtual const StringName *_get_class_namev() const {
if (!_class_name)
@@ -557,7 +547,7 @@ protected:
return &_class_name;
}
- PoolVector<String> _get_meta_list_bind() const;
+ Vector<String> _get_meta_list_bind() const;
Array _get_property_list_bind() const;
Array _get_method_list_bind() const;
@@ -566,7 +556,7 @@ protected:
friend class ClassDB;
virtual void _validate_property(PropertyInfo &property) const;
- void _disconnect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, bool p_force = false);
+ void _disconnect(const StringName &p_signal, const Callable &p_callable, bool p_force = false);
public: //should be protected, but bug in clang++
static void initialize_class();
@@ -664,7 +654,7 @@ public:
bool has_method(const StringName &p_method) const;
void get_method_list(List<MethodInfo> *p_list) const;
Variant callv(const StringName &p_method, const Array &p_args);
- virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error);
+ virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount);
virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount);
Variant call(const StringName &p_name, VARIANT_ARG_LIST); // C++ helper
@@ -679,8 +669,8 @@ public:
/* SCRIPT */
- void set_script(const RefPtr &p_script);
- RefPtr get_script() const;
+ void set_script(const Variant &p_script);
+ Variant get_script() const;
/* SCRIPT */
@@ -699,7 +689,7 @@ public:
void set_script_instance(ScriptInstance *p_instance);
_FORCE_INLINE_ ScriptInstance *get_script_instance() const { return script_instance; }
- void set_script_and_instance(const RefPtr &p_script, ScriptInstance *p_instance); //some script languages can't control instance creation, so this function eases the process
+ void set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance); //some script languages can't control instance creation, so this function eases the process
void add_user_signal(const MethodInfo &p_signal);
Error emit_signal(const StringName &p_name, VARIANT_ARG_LIST);
@@ -710,9 +700,13 @@ public:
int get_persistent_signal_connection_count() const;
void get_signals_connected_to_this(List<Connection> *p_connections) const;
- Error connect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, const Vector<Variant> &p_binds = Vector<Variant>(), uint32_t p_flags = 0);
- void disconnect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method);
- bool is_connected(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) const;
+ Error connect_compat(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, const Vector<Variant> &p_binds = Vector<Variant>(), uint32_t p_flags = 0);
+ void disconnect_compat(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method);
+ bool is_connected_compat(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) const;
+
+ Error connect(const StringName &p_signal, const Callable &p_callable, const Vector<Variant> &p_binds = Vector<Variant>(), uint32_t p_flags = 0);
+ void disconnect(const StringName &p_signal, const Callable &p_callable);
+ bool is_connected(const StringName &p_signal, const Callable &p_callable) const;
void call_deferred(const StringName &p_method, VARIANT_ARG_LIST);
void set_deferred(const StringName &p_property, const Variant &p_value);
@@ -750,6 +744,7 @@ public:
void clear_internal_resource_paths();
+ _ALWAYS_INLINE_ bool is_reference() const { return type_is_reference; }
Object();
virtual ~Object();
};
@@ -759,49 +754,63 @@ void postinitialize_handler(Object *p_object);
class ObjectDB {
- struct ObjectPtrHash {
-
- static _FORCE_INLINE_ uint32_t hash(const Object *p_obj) {
-
- union {
- const Object *p;
- unsigned long i;
- } u;
- u.p = p_obj;
- return HashMapHasherDefault::hash((uint64_t)u.i);
- }
+//this needs to add up to 63, 1 bit is for reference
+#define OBJECTDB_VALIDATOR_BITS 39
+#define OBJECTDB_VALIDATOR_MASK ((uint64_t(1) << OBJECTDB_VALIDATOR_BITS) - 1)
+#define OBJECTDB_SLOT_MAX_COUNT_BITS 24
+#define OBJECTDB_SLOT_MAX_COUNT_MASK ((uint64_t(1) << OBJECTDB_SLOT_MAX_COUNT_BITS) - 1)
+#define OBJECTDB_REFERENCE_BIT (uint64_t(1) << (OBJECTDB_SLOT_MAX_COUNT_BITS + OBJECTDB_VALIDATOR_BITS))
+
+ struct ObjectSlot { //128 bits per slot
+ uint64_t validator : OBJECTDB_VALIDATOR_BITS;
+ uint64_t next_free : OBJECTDB_SLOT_MAX_COUNT_BITS;
+ uint64_t is_reference : 1;
+ Object *object;
};
- static HashMap<ObjectID, Object *> instances;
- static HashMap<Object *, ObjectID, ObjectPtrHash> instance_checks;
+ static SpinLock spin_lock;
+ static uint32_t slot_count;
+ static uint32_t slot_max;
+ static ObjectSlot *object_slots;
+ static uint64_t validator_counter;
- static ObjectID instance_counter;
friend class Object;
friend void unregister_core_types();
-
- static RWLock *rw_lock;
static void cleanup();
+
static ObjectID add_instance(Object *p_object);
static void remove_instance(Object *p_object);
+
friend void register_core_types();
static void setup();
public:
typedef void (*DebugFunc)(Object *p_obj);
- static Object *get_instance(ObjectID p_instance_id);
- static void debug_objects(DebugFunc p_func);
- static int get_object_count();
+ _ALWAYS_INLINE_ static Object *get_instance(ObjectID p_instance_id) {
+
+ uint64_t id = p_instance_id;
+ uint32_t slot = id & OBJECTDB_SLOT_MAX_COUNT_MASK;
- _FORCE_INLINE_ static bool instance_validate(Object *p_ptr) {
- rw_lock->read_lock();
+ ERR_FAIL_COND_V(slot >= slot_max, nullptr); //this should never happen unless RID is corrupted
- bool exists = instance_checks.has(p_ptr);
+ spin_lock.lock();
- rw_lock->read_unlock();
+ uint64_t validator = (id >> OBJECTDB_SLOT_MAX_COUNT_BITS) & OBJECTDB_VALIDATOR_MASK;
- return exists;
+ if (unlikely(object_slots[slot].validator != validator)) {
+ spin_lock.unlock();
+ return nullptr;
+ }
+
+ Object *object = object_slots[slot].object;
+
+ spin_lock.unlock();
+
+ return object;
}
+ static void debug_objects(DebugFunc p_func);
+ static int get_object_count();
};
//needed by macros