You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
2.0 KiB

1 year ago
  1. #pragma once
  2. #include <type_traits>
  3. namespace vlc
  4. {
  5. template<typename T> class IntrusivePtr
  6. {
  7. public:
  8. IntrusivePtr() noexcept = default;
  9. IntrusivePtr(T* ptr, bool own = true) : m_ptr(ptr)
  10. {
  11. if (own)
  12. {
  13. intrusiveIncRef(m_ptr);
  14. }
  15. }
  16. IntrusivePtr(const IntrusivePtr& src)
  17. {
  18. *this = src;
  19. }
  20. IntrusivePtr& operator = (const IntrusivePtr& src)
  21. {
  22. intrusiveDecRef(m_ptr);
  23. m_ptr = src.m_ptr;
  24. intrusiveIncRef(m_ptr);
  25. return *this;
  26. }
  27. template<typename DerivedType> IntrusivePtr(const IntrusivePtr<DerivedType>& src)
  28. {
  29. *this = src;
  30. }
  31. template<typename DerivedType> IntrusivePtr& operator = (const IntrusivePtr<DerivedType>& src)
  32. {
  33. static_assert(std::is_base_of<T, DerivedType>::value, "Type of source pointer should be derived from this type");
  34. intrusiveDecRef(m_ptr);
  35. m_ptr = static_cast<T*>(src.get());
  36. intrusiveIncRef(m_ptr);
  37. return *this;
  38. }
  39. IntrusivePtr(IntrusivePtr&& src)
  40. {
  41. swap(src);
  42. }
  43. IntrusivePtr& operator = (IntrusivePtr&& src)
  44. {
  45. swap(src);
  46. return *this;
  47. }
  48. ~IntrusivePtr()
  49. {
  50. intrusiveDecRef(m_ptr);
  51. }
  52. explicit operator bool() const
  53. {
  54. return get() != nullptr;
  55. }
  56. void swap(IntrusivePtr& r)
  57. {
  58. std::swap(m_ptr, r.m_ptr);
  59. }
  60. void reset(T* ptr = nullptr, bool own = true)
  61. {
  62. IntrusivePtr(ptr, own).swap(*this);
  63. }
  64. T* operator -> () const
  65. {
  66. assert(m_ptr);
  67. return m_ptr;
  68. }
  69. T& operator * () const
  70. {
  71. assert(m_ptr);
  72. return *m_ptr;
  73. }
  74. T* release()
  75. {
  76. T* result = nullptr;
  77. std::swap(result, m_ptr);
  78. intrusiveDecRef(result);
  79. return result;
  80. }
  81. T* get() const
  82. {
  83. return m_ptr;
  84. }
  85. template<typename DerivedType> DerivedType* cast()
  86. {
  87. return static_cast<DerivedType*>(m_ptr);
  88. }
  89. template<typename DerivedType> const DerivedType* cast() const
  90. {
  91. return static_cast<const DerivedType*>(m_ptr);
  92. }
  93. private:
  94. T* m_ptr = nullptr;
  95. };
  96. template<typename T, typename... Args> IntrusivePtr<T> make_intrusive(Args&&... args)
  97. {
  98. return IntrusivePtr<T>(new T(std::forward<Args>(args)...));
  99. }
  100. }