ref.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "atomic.h"
  5. namespace embree
  6. {
  7. struct NullTy {
  8. };
  9. extern MAYBE_UNUSED NullTy null;
  10. class RefCount
  11. {
  12. public:
  13. RefCount(int val = 0) : refCounter(val) {}
  14. virtual ~RefCount() {};
  15. virtual RefCount* refInc() { refCounter.fetch_add(1); return this; }
  16. virtual void refDec() { if (refCounter.fetch_add(-1) == 1) delete this; }
  17. private:
  18. std::atomic<size_t> refCounter;
  19. };
  20. ////////////////////////////////////////////////////////////////////////////////
  21. /// Reference to single object
  22. ////////////////////////////////////////////////////////////////////////////////
  23. template<typename Type>
  24. class Ref
  25. {
  26. public:
  27. Type* ptr;
  28. ////////////////////////////////////////////////////////////////////////////////
  29. /// Constructors, Assignment & Cast Operators
  30. ////////////////////////////////////////////////////////////////////////////////
  31. __forceinline Ref() : ptr(nullptr) {}
  32. __forceinline Ref(NullTy) : ptr(nullptr) {}
  33. __forceinline Ref(const Ref& input) : ptr(input.ptr) { if (ptr) ptr->refInc(); }
  34. __forceinline Ref(Ref&& input) : ptr(input.ptr) { input.ptr = nullptr; }
  35. __forceinline Ref(Type* const input) : ptr(input)
  36. {
  37. if (ptr)
  38. ptr->refInc();
  39. }
  40. __forceinline ~Ref()
  41. {
  42. if (ptr)
  43. ptr->refDec();
  44. }
  45. __forceinline Ref& operator =(const Ref& input)
  46. {
  47. if (input.ptr)
  48. input.ptr->refInc();
  49. if (ptr)
  50. ptr->refDec();
  51. ptr = input.ptr;
  52. return *this;
  53. }
  54. __forceinline Ref& operator =(Ref&& input)
  55. {
  56. if (ptr)
  57. ptr->refDec();
  58. ptr = input.ptr;
  59. input.ptr = nullptr;
  60. return *this;
  61. }
  62. __forceinline Ref& operator =(Type* const input)
  63. {
  64. if (input)
  65. input->refInc();
  66. if (ptr)
  67. ptr->refDec();
  68. ptr = input;
  69. return *this;
  70. }
  71. __forceinline Ref& operator =(NullTy)
  72. {
  73. if (ptr)
  74. ptr->refDec();
  75. ptr = nullptr;
  76. return *this;
  77. }
  78. __forceinline operator bool() const { return ptr != nullptr; }
  79. __forceinline const Type& operator *() const { return *ptr; }
  80. __forceinline Type& operator *() { return *ptr; }
  81. __forceinline const Type* operator ->() const { return ptr; }
  82. __forceinline Type* operator ->() { return ptr; }
  83. template<typename TypeOut>
  84. __forceinline Ref<TypeOut> cast() { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); }
  85. template<typename TypeOut>
  86. __forceinline const Ref<TypeOut> cast() const { return Ref<TypeOut>(static_cast<TypeOut*>(ptr)); }
  87. template<typename TypeOut>
  88. __forceinline Ref<TypeOut> dynamicCast() { return Ref<TypeOut>(dynamic_cast<TypeOut*>(ptr)); }
  89. template<typename TypeOut>
  90. __forceinline const Ref<TypeOut> dynamicCast() const { return Ref<TypeOut>(dynamic_cast<TypeOut*>(ptr)); }
  91. };
  92. template<typename Type> __forceinline bool operator < (const Ref<Type>& a, const Ref<Type>& b) { return a.ptr < b.ptr; }
  93. template<typename Type> __forceinline bool operator ==(const Ref<Type>& a, NullTy ) { return a.ptr == nullptr; }
  94. template<typename Type> __forceinline bool operator ==(NullTy , const Ref<Type>& b) { return nullptr == b.ptr; }
  95. template<typename Type> __forceinline bool operator ==(const Ref<Type>& a, const Ref<Type>& b) { return a.ptr == b.ptr; }
  96. template<typename Type> __forceinline bool operator !=(const Ref<Type>& a, NullTy ) { return a.ptr != nullptr; }
  97. template<typename Type> __forceinline bool operator !=(NullTy , const Ref<Type>& b) { return nullptr != b.ptr; }
  98. template<typename Type> __forceinline bool operator !=(const Ref<Type>& a, const Ref<Type>& b) { return a.ptr != b.ptr; }
  99. }