1 /*************************************************************************/ 2 /* reference.h */ 3 /*************************************************************************/ 4 /* This file is part of: */ 5 /* GODOT ENGINE */ 6 /* https://godotengine.org */ 7 /*************************************************************************/ 8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ 9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ 10 /* */ 11 /* Permission is hereby granted, free of charge, to any person obtaining */ 12 /* a copy of this software and associated documentation files (the */ 13 /* "Software"), to deal in the Software without restriction, including */ 14 /* without limitation the rights to use, copy, modify, merge, publish, */ 15 /* distribute, sublicense, and/or sell copies of the Software, and to */ 16 /* permit persons to whom the Software is furnished to do so, subject to */ 17 /* the following conditions: */ 18 /* */ 19 /* The above copyright notice and this permission notice shall be */ 20 /* included in all copies or substantial portions of the Software. */ 21 /* */ 22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ 25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 29 /*************************************************************************/ 30 31 #ifndef REFERENCE_H 32 #define REFERENCE_H 33 34 #include "core/class_db.h" 35 #include "core/object.h" 36 #include "core/ref_ptr.h" 37 #include "core/safe_refcount.h" 38 39 class Reference : public Object { 40 41 GDCLASS(Reference, Object); 42 friend class RefBase; 43 SafeRefCount refcount; 44 SafeRefCount refcount_init; 45 46 protected: 47 static void _bind_methods(); 48 49 public: is_referenced()50 _FORCE_INLINE_ bool is_referenced() const { return refcount_init.get() != 1; } 51 bool init_ref(); 52 bool reference(); // returns false if refcount is at zero and didn't get increased 53 bool unreference(); 54 int reference_get_count() const; 55 56 Reference(); 57 ~Reference(); 58 }; 59 60 template <class T> 61 class Ref { 62 63 T *reference; 64 ref(const Ref & p_from)65 void ref(const Ref &p_from) { 66 67 if (p_from.reference == reference) 68 return; 69 70 unref(); 71 72 reference = p_from.reference; 73 if (reference) 74 reference->reference(); 75 } 76 ref_pointer(T * p_ref)77 void ref_pointer(T *p_ref) { 78 79 ERR_FAIL_COND(!p_ref); 80 81 if (p_ref->init_ref()) 82 reference = p_ref; 83 } 84 85 //virtual Reference * get_reference() const { return reference; } 86 public: 87 _FORCE_INLINE_ bool operator==(const T *p_ptr) const { 88 return reference == p_ptr; 89 } 90 _FORCE_INLINE_ bool operator!=(const T *p_ptr) const { 91 return reference != p_ptr; 92 } 93 94 _FORCE_INLINE_ bool operator<(const Ref<T> &p_r) const { 95 96 return reference < p_r.reference; 97 } 98 _FORCE_INLINE_ bool operator==(const Ref<T> &p_r) const { 99 100 return reference == p_r.reference; 101 } 102 _FORCE_INLINE_ bool operator!=(const Ref<T> &p_r) const { 103 104 return reference != p_r.reference; 105 } 106 107 _FORCE_INLINE_ T *operator->() { 108 109 return reference; 110 } 111 112 _FORCE_INLINE_ T *operator*() { 113 114 return reference; 115 } 116 117 _FORCE_INLINE_ const T *operator->() const { 118 119 return reference; 120 } 121 ptr()122 _FORCE_INLINE_ const T *ptr() const { 123 124 return reference; 125 } ptr()126 _FORCE_INLINE_ T *ptr() { 127 128 return reference; 129 } 130 131 _FORCE_INLINE_ const T *operator*() const { 132 133 return reference; 134 } 135 get_ref_ptr()136 RefPtr get_ref_ptr() const { 137 138 RefPtr refptr; 139 Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data()); 140 *irr = *this; 141 return refptr; 142 }; 143 Variant()144 operator Variant() const { 145 146 return Variant(get_ref_ptr()); 147 } 148 149 void operator=(const Ref &p_from) { 150 151 ref(p_from); 152 } 153 154 template <class T_Other> 155 void operator=(const Ref<T_Other> &p_from) { 156 157 Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr())); 158 if (!refb) { 159 unref(); 160 return; 161 } 162 Ref r; 163 r.reference = Object::cast_to<T>(refb); 164 ref(r); 165 r.reference = NULL; 166 } 167 168 void operator=(const RefPtr &p_refptr) { 169 170 Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(p_refptr.get_data()); 171 Reference *refb = irr->ptr(); 172 if (!refb) { 173 unref(); 174 return; 175 } 176 Ref r; 177 r.reference = Object::cast_to<T>(refb); 178 ref(r); 179 r.reference = NULL; 180 } 181 182 void operator=(const Variant &p_variant) { 183 184 RefPtr refptr = p_variant; 185 Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data()); 186 Reference *refb = irr->ptr(); 187 if (!refb) { 188 unref(); 189 return; 190 } 191 Ref r; 192 r.reference = Object::cast_to<T>(refb); 193 ref(r); 194 r.reference = NULL; 195 } 196 197 template <class T_Other> reference_ptr(T_Other * p_ptr)198 void reference_ptr(T_Other *p_ptr) { 199 if (reference == p_ptr) { 200 return; 201 } 202 unref(); 203 204 T *r = Object::cast_to<T>(p_ptr); 205 if (r) { 206 ref_pointer(r); 207 } 208 } 209 Ref(const Ref & p_from)210 Ref(const Ref &p_from) { 211 212 reference = NULL; 213 ref(p_from); 214 } 215 216 template <class T_Other> Ref(const Ref<T_Other> & p_from)217 Ref(const Ref<T_Other> &p_from) { 218 219 reference = NULL; 220 Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr())); 221 if (!refb) { 222 unref(); 223 return; 224 } 225 Ref r; 226 r.reference = Object::cast_to<T>(refb); 227 ref(r); 228 r.reference = NULL; 229 } 230 Ref(T * p_reference)231 Ref(T *p_reference) { 232 233 reference = NULL; 234 if (p_reference) 235 ref_pointer(p_reference); 236 } 237 Ref(const Variant & p_variant)238 Ref(const Variant &p_variant) { 239 240 RefPtr refptr = p_variant; 241 Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data()); 242 reference = NULL; 243 Reference *refb = irr->ptr(); 244 if (!refb) { 245 unref(); 246 return; 247 } 248 Ref r; 249 r.reference = Object::cast_to<T>(refb); 250 ref(r); 251 r.reference = NULL; 252 } 253 Ref(const RefPtr & p_refptr)254 Ref(const RefPtr &p_refptr) { 255 256 Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(p_refptr.get_data()); 257 reference = NULL; 258 Reference *refb = irr->ptr(); 259 if (!refb) { 260 unref(); 261 return; 262 } 263 Ref r; 264 r.reference = Object::cast_to<T>(refb); 265 ref(r); 266 r.reference = NULL; 267 } 268 is_valid()269 inline bool is_valid() const { return reference != NULL; } is_null()270 inline bool is_null() const { return reference == NULL; } 271 unref()272 void unref() { 273 //TODO this should be moved to mutexes, since this engine does not really 274 // do a lot of referencing on references and stuff 275 // mutexes will avoid more crashes? 276 277 if (reference && reference->unreference()) { 278 279 memdelete(reference); 280 } 281 reference = NULL; 282 } 283 instance()284 void instance() { 285 ref(memnew(T)); 286 } 287 Ref()288 Ref() { 289 290 reference = NULL; 291 } 292 ~Ref()293 ~Ref() { 294 295 unref(); 296 } 297 }; 298 299 typedef Ref<Reference> REF; 300 301 class WeakRef : public Reference { 302 303 GDCLASS(WeakRef, Reference); 304 305 ObjectID ref; 306 307 protected: 308 static void _bind_methods(); 309 310 public: 311 Variant get_ref() const; 312 void set_obj(Object *p_object); 313 void set_ref(const REF &p_ref); 314 315 WeakRef(); 316 }; 317 318 #ifdef PTRCALL_ENABLED 319 320 template <class T> 321 struct PtrToArg<Ref<T> > { 322 323 _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) { 324 325 return Ref<T>(const_cast<T *>(reinterpret_cast<const T *>(p_ptr))); 326 } 327 328 _FORCE_INLINE_ static void encode(Ref<T> p_val, const void *p_ptr) { 329 330 *(Ref<Reference> *)p_ptr = p_val; 331 } 332 }; 333 334 template <class T> 335 struct PtrToArg<const Ref<T> &> { 336 337 _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) { 338 339 return Ref<T>((T *)p_ptr); 340 } 341 }; 342 343 //this is for RefPtr 344 345 template <> 346 struct PtrToArg<RefPtr> { 347 348 _FORCE_INLINE_ static RefPtr convert(const void *p_ptr) { 349 350 return Ref<Reference>(const_cast<Reference *>(reinterpret_cast<const Reference *>(p_ptr))).get_ref_ptr(); 351 } 352 353 _FORCE_INLINE_ static void encode(RefPtr p_val, const void *p_ptr) { 354 355 Ref<Reference> r = p_val; 356 *(Ref<Reference> *)p_ptr = r; 357 } 358 }; 359 360 template <> 361 struct PtrToArg<const RefPtr &> { 362 363 _FORCE_INLINE_ static RefPtr convert(const void *p_ptr) { 364 365 return Ref<Reference>(const_cast<Reference *>(reinterpret_cast<const Reference *>(p_ptr))).get_ref_ptr(); 366 } 367 }; 368 369 #endif // PTRCALL_ENABLED 370 371 #ifdef DEBUG_METHODS_ENABLED 372 373 template <class T> 374 struct GetTypeInfo<Ref<T> > { 375 static const Variant::Type VARIANT_TYPE = Variant::OBJECT; 376 static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; 377 378 static inline PropertyInfo get_class_info() { 379 return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static()); 380 } 381 }; 382 383 template <class T> 384 struct GetTypeInfo<const Ref<T> &> { 385 static const Variant::Type VARIANT_TYPE = Variant::OBJECT; 386 static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; 387 388 static inline PropertyInfo get_class_info() { 389 return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, T::get_class_static()); 390 } 391 }; 392 393 #endif // DEBUG_METHODS_ENABLED 394 395 #endif // REFERENCE_H 396