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