1 /*************************************************************************/ 2 /* reference.h */ 3 /*************************************************************************/ 4 /* This file is part of: */ 5 /* GODOT ENGINE */ 6 /* https://godotengine.org */ 7 /*************************************************************************/ 8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ 9 /* Copyright (c) 2014-2019 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 #ifndef REFERENCE_H 31 #define REFERENCE_H 32 33 #include "object.h" 34 #include "object_type_db.h" 35 #include "ref_ptr.h" 36 #include "safe_refcount.h" 37 38 /** 39 @author Juan Linietsky <reduzio@gmail.com> 40 */ 41 class Reference : public Object { 42 43 OBJ_TYPE(Reference, Object); 44 friend class RefBase; 45 SafeRefCount refcount; 46 SafeRefCount refcount_init; 47 48 protected: 49 static void _bind_methods(); 50 51 public: is_referenced()52 _FORCE_INLINE_ bool is_referenced() const { return refcount_init.get() < 1; } 53 bool init_ref(); 54 void reference(); 55 bool unreference(); 56 int reference_get_count() const; 57 58 Reference(); 59 ~Reference(); 60 }; 61 62 #if 0 63 class RefBase { 64 protected: 65 void ref_inc(Reference *p_reference); 66 bool ref_dec(Reference *p_reference); 67 Reference *first_ref(Reference *p_reference); 68 Reference * get_reference_from_ref(const RefBase &p_base); 69 virtual Reference * get_reference() const=0; 70 char * get_refptr_data(const RefPtr &p_refptr) const; 71 public: 72 ~RefBase()73 virtual ~RefBase() {} 74 }; 75 #endif 76 77 template <class T> 78 class Ref { 79 80 T *reference; 81 ref(const Ref & p_from)82 void ref(const Ref &p_from) { 83 84 if (p_from.reference == reference) 85 return; 86 87 unref(); 88 89 reference = p_from.reference; 90 if (reference) 91 reference->reference(); 92 } 93 ref_pointer(T * p_ref)94 void ref_pointer(T *p_ref) { 95 96 ERR_FAIL_COND(!p_ref); 97 98 if (p_ref->init_ref()) 99 reference = p_ref; 100 } 101 102 //virtual Reference * get_reference() const { return reference; } 103 public: 104 _FORCE_INLINE_ bool operator<(const Ref<T> &p_r) const { 105 106 return reference < p_r.reference; 107 } 108 _FORCE_INLINE_ bool operator==(const Ref<T> &p_r) const { 109 110 return reference == p_r.reference; 111 } 112 _FORCE_INLINE_ bool operator!=(const Ref<T> &p_r) const { 113 114 return reference != p_r.reference; 115 } 116 117 _FORCE_INLINE_ T *operator->() { 118 119 return reference; 120 } 121 122 _FORCE_INLINE_ T *operator*() { 123 124 return reference; 125 } 126 127 _FORCE_INLINE_ const T *operator->() const { 128 129 return reference; 130 } 131 ptr()132 _FORCE_INLINE_ const T *ptr() const { 133 134 return reference; 135 } ptr()136 _FORCE_INLINE_ T *ptr() { 137 138 return reference; 139 } 140 141 _FORCE_INLINE_ const T *operator*() const { 142 143 return reference; 144 } 145 get_ref_ptr()146 RefPtr get_ref_ptr() const { 147 148 RefPtr refptr; 149 Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data()); 150 *irr = *this; 151 return refptr; 152 }; 153 154 #if 0 155 // go to RefPtr RefPtr()156 operator RefPtr() const { 157 158 return get_ref_ptr(); 159 } 160 #endif 161 162 #if 1 Variant()163 operator Variant() const { 164 165 return Variant(get_ref_ptr()); 166 } 167 #endif 168 169 void operator=(const Ref &p_from) { 170 171 ref(p_from); 172 } 173 174 template <class T_Other> 175 void operator=(const Ref<T_Other> &p_from) { 176 177 Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr())); 178 if (!refb) { 179 unref(); 180 return; 181 } 182 Ref r; 183 r.reference = refb->cast_to<T>(); 184 ref(r); 185 r.reference = NULL; 186 } 187 188 void operator=(const RefPtr &p_refptr) { 189 190 Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(p_refptr.get_data()); 191 Reference *refb = irr->ptr(); 192 if (!refb) { 193 unref(); 194 return; 195 } 196 Ref r; 197 r.reference = refb->cast_to<T>(); 198 ref(r); 199 r.reference = NULL; 200 } 201 202 void operator=(const Variant &p_variant) { 203 204 RefPtr refptr = p_variant; 205 Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data()); 206 Reference *refb = irr->ptr(); 207 if (!refb) { 208 unref(); 209 return; 210 } 211 Ref r; 212 r.reference = refb->cast_to<T>(); 213 ref(r); 214 r.reference = NULL; 215 } 216 Ref(const Ref & p_from)217 Ref(const Ref &p_from) { 218 219 reference = NULL; 220 ref(p_from); 221 } 222 223 template <class T_Other> Ref(const Ref<T_Other> & p_from)224 Ref(const Ref<T_Other> &p_from) { 225 226 reference = NULL; 227 Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr())); 228 if (!refb) { 229 unref(); 230 return; 231 } 232 Ref r; 233 r.reference = refb->cast_to<T>(); 234 ref(r); 235 r.reference = NULL; 236 } 237 Ref(T * p_reference)238 Ref(T *p_reference) { 239 240 if (p_reference) 241 ref_pointer(p_reference); 242 else 243 reference = NULL; 244 } 245 Ref(const Variant & p_variant)246 Ref(const Variant &p_variant) { 247 248 RefPtr refptr = p_variant; 249 Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data()); 250 reference = NULL; 251 Reference *refb = irr->ptr(); 252 if (!refb) { 253 unref(); 254 return; 255 } 256 Ref r; 257 r.reference = refb->cast_to<T>(); 258 ref(r); 259 r.reference = NULL; 260 } 261 Ref(const RefPtr & p_refptr)262 Ref(const RefPtr &p_refptr) { 263 264 Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(p_refptr.get_data()); 265 reference = NULL; 266 Reference *refb = irr->ptr(); 267 if (!refb) { 268 unref(); 269 return; 270 } 271 Ref r; 272 r.reference = refb->cast_to<T>(); 273 ref(r); 274 r.reference = NULL; 275 } 276 is_valid()277 inline bool is_valid() const { return reference != NULL; } is_null()278 inline bool is_null() const { return reference == NULL; } 279 unref()280 void unref() { 281 //TODO this should be moved to mutexes, since this engine does not really 282 // do a lot of referencing on references and stuff 283 // mutexes will avoid more crashes? 284 285 if (reference && reference->unreference()) { 286 287 memdelete(reference); 288 } 289 reference = NULL; 290 } 291 instance()292 void instance() { 293 ref(memnew(T)); 294 } 295 Ref()296 Ref() { 297 298 reference = NULL; 299 } 300 ~Ref()301 ~Ref() { 302 303 unref(); 304 } 305 }; 306 307 typedef Ref<Reference> REF; 308 309 class WeakRef : public Reference { 310 311 OBJ_TYPE(WeakRef, Reference); 312 313 ObjectID ref; 314 315 protected: 316 static void _bind_methods(); 317 318 public: 319 Variant get_ref() const; 320 void set_obj(Object *p_object); 321 void set_ref(const REF &p_ref); 322 323 WeakRef(); 324 }; 325 326 #ifdef PTRCALL_ENABLED 327 328 template <class T> 329 struct PtrToArg<Ref<T> > { 330 331 _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) { 332 333 return Ref<T>(reinterpret_cast<const T *>(p_ptr)); 334 } 335 336 _FORCE_INLINE_ static void encode(Ref<T> p_val, const void *p_ptr) { 337 338 *(Ref<Reference> *)p_ptr = p_val; 339 } 340 }; 341 342 template <class T> 343 struct PtrToArg<const Ref<T> &> { 344 345 _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) { 346 347 return Ref<T>(reinterpret_cast<const T *>(p_ptr)); 348 } 349 }; 350 351 //this is for RefPtr 352 353 template <> 354 struct PtrToArg<RefPtr> { 355 356 _FORCE_INLINE_ static RefPtr convert(const void *p_ptr) { 357 358 return Ref<Reference>(reinterpret_cast<const Reference *>(p_ptr)).get_ref_ptr(); 359 } 360 361 _FORCE_INLINE_ static void encode(RefPtr p_val, const void *p_ptr) { 362 363 Ref<Reference> r = p_val; 364 *(Ref<Reference> *)p_ptr = r; 365 } 366 }; 367 368 template <> 369 struct PtrToArg<const RefPtr &> { 370 371 _FORCE_INLINE_ static RefPtr convert(const void *p_ptr) { 372 373 return Ref<Reference>(reinterpret_cast<const Reference *>(p_ptr)).get_ref_ptr(); 374 } 375 }; 376 377 #endif 378 #endif // REFERENCE_H 379