Ref.hpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #ifndef REF_H
  2. #define REF_H
  3. #include "GodotGlobal.hpp"
  4. #include "Reference.hpp"
  5. #include "Variant.hpp"
  6. namespace godot {
  7. // Replicates Godot's Ref<T> behavior
  8. // Rewritten from f5234e70be7dec4930c2d5a0e829ff480d044b1d.
  9. template <class T>
  10. class Ref {
  11. // TODO For this nice check to work, each class must actually #include Reference classes mentionned in its methods,
  12. // which might be annoying for coders who prefer to forward-declare to reduce compile times
  13. // static_assert(std::is_base_of<Reference, T>::value,
  14. // "Ref<T> can only be used with classes deriving from Reference");
  15. T *reference = nullptr;
  16. void ref(const Ref &p_from) {
  17. if (p_from.reference == reference)
  18. return;
  19. unref();
  20. reference = p_from.reference;
  21. if (reference)
  22. reference->reference();
  23. }
  24. void ref_pointer(T *p_ref) {
  25. ERR_FAIL_COND(p_ref == nullptr);
  26. if (p_ref->init_ref())
  27. reference = p_ref;
  28. }
  29. public:
  30. inline bool operator<(const Ref<T> &p_r) const {
  31. return reference < p_r.reference;
  32. }
  33. inline bool operator==(const Ref<T> &p_r) const {
  34. return reference == p_r.reference;
  35. }
  36. inline bool operator!=(const Ref<T> &p_r) const {
  37. return reference != p_r.reference;
  38. }
  39. inline T *operator->() {
  40. return reference;
  41. }
  42. inline T *operator*() {
  43. return reference;
  44. }
  45. inline const T *operator->() const {
  46. return reference;
  47. }
  48. inline const T *ptr() const {
  49. return reference;
  50. }
  51. inline T *ptr() {
  52. return reference;
  53. }
  54. inline const T *operator*() const {
  55. return reference;
  56. }
  57. operator Variant() const {
  58. // Note: the C API handles the cases where the object is a Reference,
  59. // so the Variant will be correctly constructed with a RefPtr engine-side
  60. return Variant((Object *)reference);
  61. }
  62. void operator=(const Ref &p_from) {
  63. ref(p_from);
  64. }
  65. template <class T_Other>
  66. void operator=(const Ref<T_Other> &p_from) {
  67. Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr()));
  68. if (refb == nullptr) {
  69. unref();
  70. return;
  71. }
  72. Ref r;
  73. r.reference = Object::cast_to<T>(refb);
  74. ref(r);
  75. r.reference = nullptr;
  76. }
  77. void operator=(const Variant &p_variant) {
  78. Object *refb = T::___get_from_variant(p_variant);
  79. if (refb == nullptr) {
  80. unref();
  81. return;
  82. }
  83. Ref r;
  84. r.reference = Object::cast_to<T>(refb);
  85. ref(r);
  86. r.reference = nullptr;
  87. }
  88. Ref(const Ref &p_from) {
  89. reference = nullptr;
  90. ref(p_from);
  91. }
  92. template <class T_Other>
  93. Ref(const Ref<T_Other> &p_from) {
  94. reference = nullptr;
  95. Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr()));
  96. if (refb == nullptr) {
  97. unref();
  98. return;
  99. }
  100. Ref r;
  101. r.reference = Object::cast_to<T>(refb);
  102. ref(r);
  103. r.reference = nullptr;
  104. }
  105. Ref(T *p_reference) {
  106. if (p_reference)
  107. ref_pointer(p_reference);
  108. else
  109. reference = nullptr;
  110. }
  111. Ref(const Variant &p_variant) {
  112. reference = nullptr;
  113. Object *refb = T::___get_from_variant(p_variant);
  114. if (refb == nullptr) {
  115. unref();
  116. return;
  117. }
  118. Ref r;
  119. r.reference = Object::cast_to<T>(refb);
  120. ref(r);
  121. r.reference = nullptr;
  122. }
  123. inline bool is_valid() const { return reference != nullptr; }
  124. inline bool is_null() const { return reference == nullptr; }
  125. void unref() {
  126. //TODO this should be moved to mutexes, since this engine does not really
  127. // do a lot of referencing on references and stuff
  128. // mutexes will avoid more crashes?
  129. if (reference && reference->unreference()) {
  130. //memdelete(reference);
  131. reference->free();
  132. }
  133. reference = nullptr;
  134. }
  135. void instance() {
  136. //ref(memnew(T));
  137. ref(T::_new());
  138. }
  139. Ref() {
  140. reference = nullptr;
  141. }
  142. ~Ref() {
  143. unref();
  144. }
  145. // Used exclusively in the bindings to recreate the Ref Godot encapsulates in return values,
  146. // without adding to the refcount.
  147. inline static Ref<T> __internal_constructor(Object *obj) {
  148. Ref<T> r;
  149. r.reference = (T *)obj;
  150. return r;
  151. }
  152. };
  153. } // namespace godot
  154. #endif