Skip to content

Commit ef6b34d

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

2 files changed

Lines changed: 64 additions & 80 deletions

File tree

binding_generator.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,6 +1676,8 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
16761676
used_classes = list(used_classes)
16771677
used_classes.sort()
16781678
fully_used_classes = list(fully_used_classes)
1679+
if class_api["name"] == "RefCounted":
1680+
fully_used_classes.remove("Ref") # Special case; Ref should include RefCounted but not vice versa.
16791681
fully_used_classes.sort()
16801682

16811683
with header_filename.open("w+", encoding="utf-8") as header_file:

include/godot_cpp/classes/ref.hpp

Lines changed: 62 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -42,30 +42,34 @@ namespace godot {
4242

4343
// Helper class for RefCounted objects, same as Godot one.
4444

45-
class RefCounted;
46-
4745
template <typename T>
4846
class Ref {
4947
T *reference = nullptr;
5048

51-
void ref(const Ref &p_from) {
52-
if (p_from.reference == reference) {
49+
_FORCE_INLINE_ void ref(const Ref &p_from) {
50+
ref_pointer<false>(p_from.reference);
51+
}
52+
53+
template <bool Init>
54+
_FORCE_INLINE_ void ref_pointer(T *p_refcounted) {
55+
if (p_refcounted == reference) {
5356
return;
5457
}
5558

56-
unref();
57-
58-
reference = p_from.reference;
59+
// This will go out of scope and get unref'd.
60+
Ref cleanup_ref;
61+
cleanup_ref.reference = reference;
62+
reference = p_refcounted;
5963
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;
64+
if constexpr (Init) {
65+
if (!reference->init_ref()) {
66+
reference = nullptr;
67+
}
68+
} else {
69+
if (!reference->reference()) {
70+
reference = nullptr;
71+
}
72+
}
6973
}
7074
}
7175

@@ -111,110 +115,88 @@ class Ref {
111115
ref(p_from);
112116
}
113117

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();
118+
void operator=(Ref &&p_from) {
119+
if (reference == p_from.reference) {
119120
return;
120121
}
122+
unref();
123+
reference = p_from.reference;
124+
p_from.reference = nullptr;
125+
}
121126

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

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

131-
// Object *object = p_variant.get_validated_object();
132-
Object *object = p_variant;
136+
void operator=(const Variant &p_variant) {
137+
Object *object = p_variant.get_validated_object();
133138

134139
if (object == reference) {
135140
return;
136141
}
137142

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-
}
143+
ref_pointer<false>(Object::cast_to<T>(object));
148144
}
149145

150146
template <typename T_Other>
151147
void reference_ptr(T_Other *p_ptr) {
152148
if (reference == p_ptr) {
153149
return;
154150
}
155-
unref();
156151

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

163155
Ref(const Ref &p_from) {
164-
ref(p_from);
156+
this->operator=(p_from);
157+
}
158+
159+
Ref(Ref &&p_from) {
160+
reference = p_from.reference;
161+
p_from.reference = nullptr;
165162
}
166163

167164
template <typename T_Other>
168165
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;
166+
this->operator=(p_from);
179167
}
180168

181-
Ref(T *p_reference) {
182-
if (p_reference) {
183-
ref_pointer(p_reference);
184-
}
169+
Ref(T *p_from) {
170+
this->operator=(p_from);
185171
}
186172

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-
}
173+
Ref(const Variant &p_from) {
174+
this->operator=(p_from);
201175
}
202176

203177
inline bool is_valid() const { return reference != nullptr; }
204178
inline bool is_null() const { return reference == nullptr; }
205179

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

213-
void instantiate() {
214-
ref(memnew(T()));
192+
template <typename... VarArgs>
193+
void instantiate(VarArgs... p_params) {
194+
ref(memnew(T(p_params...)));
215195
}
216196

217-
Ref() {}
197+
uint32_t hash() const { return HashMapHasherDefault::hash(reference); }
198+
199+
Ref() = default;
218200

219201
~Ref() {
220202
unref();
@@ -224,7 +206,7 @@ class Ref {
224206
// without adding to the refcount.
225207
inline static Ref<T> _gde_internal_constructor(Object *obj) {
226208
Ref<T> r;
227-
r.reference = (T *)obj;
209+
r.reference = reinterpret_cast<T *>(obj);
228210
return r;
229211
}
230212
};

0 commit comments

Comments
 (0)