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.

160 lines
4.3 KiB

  1. #if !defined(__OBJECT_H)
  2. #define __OBJECT_H
  3. #include <atomic>
  4. /// Reference counted object base class
  5. class Object {
  6. public:
  7. /// Default constructor
  8. Object() { }
  9. /// Copy constructor
  10. Object(const Object &) : m_refCount(0) {}
  11. /// Return the current reference count
  12. int getRefCount() const { return m_refCount; };
  13. /// Increase the object's reference count by one
  14. void incRef() const { ++m_refCount; }
  15. /** \brief Decrease the reference count of
  16. * the object and possibly deallocate it.
  17. *
  18. * The object will automatically be deallocated once
  19. * the reference count reaches zero.
  20. */
  21. void decRef(bool dealloc = true) const {
  22. --m_refCount;
  23. if (m_refCount == 0 && dealloc)
  24. delete this;
  25. else if (m_refCount < 0)
  26. throw std::runtime_error("Internal error: reference count < 0!");
  27. }
  28. virtual std::string toString() const = 0;
  29. protected:
  30. /** \brief Virtual protected deconstructor.
  31. * (Will only be called by \ref ref)
  32. */
  33. virtual ~Object() { }
  34. private:
  35. mutable std::atomic<int> m_refCount { 0 };
  36. };
  37. /**
  38. * \brief Reference counting helper
  39. *
  40. * The \a ref refeference template is a simple wrapper to store a
  41. * pointer to an object. It takes care of increasing and decreasing
  42. * the reference count of the object. When the last reference goes
  43. * out of scope, the associated object will be deallocated.
  44. *
  45. * \ingroup libcore
  46. */
  47. template <typename T> class ref {
  48. public:
  49. /// Create a nullptr reference
  50. ref() : m_ptr(nullptr) { std::cout << "Created empty ref" << std::endl; }
  51. /// Construct a reference from a pointer
  52. ref(T *ptr) : m_ptr(ptr) {
  53. std::cout << "Initialized ref from pointer " << ptr<< std::endl;
  54. if (m_ptr) ((Object *) m_ptr)->incRef();
  55. }
  56. /// Copy constructor
  57. ref(const ref &r) : m_ptr(r.m_ptr) {
  58. std::cout << "Initialized ref from ref " << r.m_ptr << std::endl;
  59. if (m_ptr)
  60. ((Object *) m_ptr)->incRef();
  61. }
  62. /// Move constructor
  63. ref(ref &&r) : m_ptr(r.m_ptr) {
  64. std::cout << "Initialized ref with move from ref " << r.m_ptr << std::endl;
  65. r.m_ptr = nullptr;
  66. }
  67. /// Destroy this reference
  68. ~ref() {
  69. std::cout << "Destructing ref " << m_ptr << std::endl;
  70. if (m_ptr)
  71. ((Object *) m_ptr)->decRef();
  72. }
  73. /// Move another reference into the current one
  74. ref& operator=(ref&& r) {
  75. std::cout << "Move-assigning ref " << r.m_ptr << std::endl;
  76. if (*this == r)
  77. return *this;
  78. if (m_ptr)
  79. ((Object *) m_ptr)->decRef();
  80. m_ptr = r.m_ptr;
  81. r.m_ptr = nullptr;
  82. return *this;
  83. }
  84. /// Overwrite this reference with another reference
  85. ref& operator=(const ref& r) {
  86. std::cout << "Assigning ref " << r.m_ptr << std::endl;
  87. if (m_ptr == r.m_ptr)
  88. return *this;
  89. if (m_ptr)
  90. ((Object *) m_ptr)->decRef();
  91. m_ptr = r.m_ptr;
  92. if (m_ptr)
  93. ((Object *) m_ptr)->incRef();
  94. return *this;
  95. }
  96. /// Overwrite this reference with a pointer to another object
  97. ref& operator=(T *ptr) {
  98. std::cout << "Assigning ptr " << ptr << " to ref" << std::endl;
  99. if (m_ptr == ptr)
  100. return *this;
  101. if (m_ptr)
  102. ((Object *) m_ptr)->decRef();
  103. m_ptr = ptr;
  104. if (m_ptr)
  105. ((Object *) m_ptr)->incRef();
  106. return *this;
  107. }
  108. /// Compare this reference with another reference
  109. bool operator==(const ref &r) const { return m_ptr == r.m_ptr; }
  110. /// Compare this reference with another reference
  111. bool operator!=(const ref &r) const { return m_ptr != r.m_ptr; }
  112. /// Compare this reference with a pointer
  113. bool operator==(const T* ptr) const { return m_ptr == ptr; }
  114. /// Compare this reference with a pointer
  115. bool operator!=(const T* ptr) const { return m_ptr != ptr; }
  116. /// Access the object referenced by this reference
  117. T* operator->() { return m_ptr; }
  118. /// Access the object referenced by this reference
  119. const T* operator->() const { return m_ptr; }
  120. /// Return a C++ reference to the referenced object
  121. T& operator*() { return *m_ptr; }
  122. /// Return a const C++ reference to the referenced object
  123. const T& operator*() const { return *m_ptr; }
  124. /// Return a pointer to the referenced object
  125. operator T* () { return m_ptr; }
  126. /// Return a const pointer to the referenced object
  127. T* get() { return m_ptr; }
  128. /// Return a pointer to the referenced object
  129. const T* get() const { return m_ptr; }
  130. private:
  131. T *m_ptr;
  132. };
  133. #endif /* __OBJECT_H */