@@ -48,24 +48,30 @@ template <typename T>
4848class 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