Skip to content

Commit 8a733d8

Browse files
committed
Sync Ref to godotengine master.
1 parent 713481f commit 8a733d8

1 file changed

Lines changed: 62 additions & 78 deletions

File tree

include/godot_cpp/classes/ref.hpp

Lines changed: 62 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -48,24 +48,30 @@ template <typename T>
4848
class Ref {
4949
T *reference = nullptr;
5050

51-
void ref(const Ref &p_from) {
52-
if (p_from.reference == reference) {
51+
_FORCE_INLINE_ void ref(const Ref &p_from) {
52+
ref_pointer<false>(p_from.reference);
53+
}
54+
55+
template <bool Init>
56+
_FORCE_INLINE_ void ref_pointer(T *p_refcounted) {
57+
if (p_refcounted == reference) {
5358
return;
5459
}
5560

56-
unref();
57-
58-
reference = p_from.reference;
61+
// This will go out of scope and get unref'd.
62+
Ref cleanup_ref;
63+
cleanup_ref.reference = reference;
64+
reference = p_refcounted;
5965
if (reference) {
60-
reference->reference();
61-
}
62-
}
63-
64-
void ref_pointer(T *p_ref) {
65-
ERR_FAIL_NULL(p_ref);
66-
67-
if (p_ref->init_ref()) {
68-
reference = p_ref;
66+
if constexpr (Init) {
67+
if (!reference->init_ref()) {
68+
reference = nullptr;
69+
}
70+
} else {
71+
if (!reference->reference()) {
72+
reference = nullptr;
73+
}
74+
}
6975
}
7076
}
7177

@@ -111,110 +117,88 @@ class Ref {
111117
ref(p_from);
112118
}
113119

114-
template <typename T_Other>
115-
void operator=(const Ref<T_Other> &p_from) {
116-
RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
117-
if (!refb) {
118-
unref();
120+
void operator=(Ref &&p_from) {
121+
if (reference == p_from.reference) {
119122
return;
120123
}
124+
unref();
125+
reference = p_from.reference;
126+
p_from.reference = nullptr;
127+
}
121128

122-
Ref r;
123-
r.reference = Object::cast_to<T>(refb);
124-
ref(r);
125-
r.reference = nullptr;
129+
template <typename T_Other>
130+
void operator=(const Ref<T_Other> &p_from) {
131+
ref_pointer<false>(Object::cast_to<T>(p_from.ptr()));
126132
}
127133

128-
void operator=(const Variant &p_variant) {
129-
// Needs testing, Variant has a cast to Object * here.
134+
void operator=(T *p_from) {
135+
ref_pointer<true>(p_from);
136+
}
130137

131-
// Object *object = p_variant.get_validated_object();
132-
Object *object = p_variant;
138+
void operator=(const Variant &p_variant) {
139+
Object *object = p_variant.get_validated_object();
133140

134141
if (object == reference) {
135142
return;
136143
}
137144

138-
unref();
139-
140-
if (!object) {
141-
return;
142-
}
143-
144-
T *r = Object::cast_to<T>(object);
145-
if (r && r->reference()) {
146-
reference = r;
147-
}
145+
ref_pointer<false>(Object::cast_to<T>(object));
148146
}
149147

150148
template <typename T_Other>
151149
void reference_ptr(T_Other *p_ptr) {
152150
if (reference == p_ptr) {
153151
return;
154152
}
155-
unref();
156153

157-
T *r = Object::cast_to<T>(p_ptr);
158-
if (r) {
159-
ref_pointer(r);
160-
}
154+
ref_pointer<true>(Object::cast_to<T>(p_ptr));
161155
}
162156

163157
Ref(const Ref &p_from) {
164-
ref(p_from);
158+
this->operator=(p_from);
159+
}
160+
161+
Ref(Ref &&p_from) {
162+
reference = p_from.reference;
163+
p_from.reference = nullptr;
165164
}
166165

167166
template <typename T_Other>
168167
Ref(const Ref<T_Other> &p_from) {
169-
RefCounted *refb = const_cast<RefCounted *>(static_cast<const RefCounted *>(p_from.ptr()));
170-
if (!refb) {
171-
unref();
172-
return;
173-
}
174-
175-
Ref r;
176-
r.reference = Object::cast_to<T>(refb);
177-
ref(r);
178-
r.reference = nullptr;
168+
this->operator=(p_from);
179169
}
180170

181-
Ref(T *p_reference) {
182-
if (p_reference) {
183-
ref_pointer(p_reference);
184-
}
171+
Ref(T *p_from) {
172+
this->operator=(p_from);
185173
}
186174

187-
Ref(const Variant &p_variant) {
188-
// Needs testing, Variant has a cast to Object * here.
189-
190-
// Object *object = p_variant.get_validated_object();
191-
Object *object = p_variant;
192-
193-
if (!object) {
194-
return;
195-
}
196-
197-
T *r = Object::cast_to<T>(object);
198-
if (r && r->reference()) {
199-
reference = r;
200-
}
175+
Ref(const Variant &p_from) {
176+
this->operator=(p_from);
201177
}
202178

203179
inline bool is_valid() const { return reference != nullptr; }
204180
inline bool is_null() const { return reference == nullptr; }
205181

206182
void unref() {
207-
if (reference && reference->unreference()) {
208-
memdelete(reference);
183+
if (reference) {
184+
// NOTE: `reinterpret_cast` is "safe" here because we know `T` has simple linear
185+
// inheritance to `RefCounted`. This guarantees that `T * == `RefCounted *`, which
186+
// allows us to declare `Ref<T>` with forward declared `T` types.
187+
if (reinterpret_cast<RefCounted *>(reference)->unreference()) {
188+
memdelete(reinterpret_cast<RefCounted *>(reference));
189+
}
190+
reference = nullptr;
209191
}
210-
reference = nullptr;
211192
}
212193

213-
void instantiate() {
214-
ref(memnew(T()));
194+
template <typename... VarArgs>
195+
void instantiate(VarArgs... p_params) {
196+
ref(memnew(T(p_params...)));
215197
}
216198

217-
Ref() {}
199+
uint32_t hash() const { return HashMapHasherDefault::hash(reference); }
200+
201+
Ref() = default;
218202

219203
~Ref() {
220204
unref();
@@ -224,7 +208,7 @@ class Ref {
224208
// without adding to the refcount.
225209
inline static Ref<T> _gde_internal_constructor(Object *obj) {
226210
Ref<T> r;
227-
r.reference = (T *)obj;
211+
r.reference = reinterpret_cast<T *>(obj);
228212
return r;
229213
}
230214
};

0 commit comments

Comments
 (0)