Line data Source code
1 :
2 : /* Copyright (c) 2005-2015, Stefan Eilemann <eile@equalizergraphics.com>
3 : * Daniel Nachbaur <danielnachbaur@gmail.com>
4 : *
5 : * This library is free software; you can redistribute it and/or modify it under
6 : * the terms of the GNU Lesser General Public License version 2.1 as published
7 : * by the Free Software Foundation.
8 : *
9 : * This library is distributed in the hope that it will be useful, but WITHOUT
10 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 : * details.
13 : *
14 : * You should have received a copy of the GNU Lesser General Public License
15 : * along with this library; if not, write to the Free Software Foundation, Inc.,
16 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 : */
18 :
19 : #ifndef LUNCHBOX_REFPTR_H
20 : #define LUNCHBOX_REFPTR_H
21 :
22 : #include <lunchbox/debug.h>
23 :
24 : #include <iostream>
25 : #include <stdlib.h>
26 :
27 : namespace lunchbox
28 : {
29 : /**
30 : * A smart reference pointer, aka boost::intrusive_ptr.
31 : *
32 : * Relies on the held object to implement ref() and unref()
33 : * correctly. Serializable using boost.serialization.
34 : *
35 : * @deprecated Use boost::intrusive_ptr
36 : *
37 : * Example: @include tests/refPtr.cpp
38 : */
39 : template <class T>
40 : class RefPtr
41 : {
42 : typedef T* RefPtr::*bool_t;
43 :
44 : public:
45 : /** Construct a new, empty reference pointer. @version 1.0 */
46 25 : RefPtr()
47 25 : : _ptr(0)
48 : {
49 25 : }
50 :
51 : /** Construct a reference pointer from a C pointer. @version 1.0 */
52 : // cppcheck-suppress noExplicitConstructor
53 2000007 : RefPtr(T* const ptr)
54 2000007 : : _ptr(ptr)
55 : {
56 2000007 : _ref();
57 2000007 : }
58 :
59 : /** Construct a copy of a reference pointer. @version 1.0 */
60 3000007 : RefPtr(const RefPtr& from)
61 3000007 : : _ptr(from._ptr)
62 : {
63 3000007 : _ref();
64 3000007 : }
65 :
66 : /**
67 : * Construct a copy of a reference pointer of a different type.
68 : * @version 1.0
69 : */
70 : // cppcheck-suppress noExplicitConstructor
71 : template <class O>
72 : RefPtr(RefPtr<O> from)
73 : : _ptr(from.get())
74 : {
75 : _ref();
76 : }
77 :
78 : /** Destruct this reference pointer. @version 1.0 */
79 5000039 : ~RefPtr()
80 : {
81 5000039 : _unref();
82 5000039 : _ptr = 0;
83 5000039 : }
84 :
85 : /** Assign another RefPtr to this reference pointer. @version 1.0 */
86 6647494 : RefPtr& operator=(const RefPtr& rhs)
87 : {
88 6647494 : if (_ptr == rhs._ptr)
89 3138848 : return *this;
90 :
91 3508646 : T* tmp = _ptr;
92 3508646 : _ptr = rhs._ptr;
93 3508646 : _ref();
94 3562459 : if (tmp)
95 0 : tmp->unref(this);
96 3651250 : return *this;
97 : }
98 :
99 : /** Assign a C pointer to this reference pointer. @version 1.0 */
100 3376586 : RefPtr& operator=(T* ptr)
101 : {
102 3376586 : if (_ptr == ptr)
103 0 : return *this;
104 :
105 3376586 : T* tmp = _ptr;
106 3376586 : _ptr = ptr;
107 3376586 : _ref();
108 3712421 : if (tmp)
109 3784396 : tmp->unref(this);
110 3384577 : return *this;
111 : }
112 :
113 : /**
114 : * @return true if both reference pointers hold the same C pointer.
115 : * @version 1.0
116 : */
117 : bool operator==(const RefPtr& rhs) const { return (_ptr == rhs._ptr); }
118 : /**
119 : * @return true if both reference pointer hold different C pointer.
120 : * @version 1.0
121 : */
122 : bool operator!=(const RefPtr& rhs) const { return (_ptr != rhs._ptr); }
123 : /**
124 : * @return true if a pointer is held, false otherwise.
125 : * @version 1.1.5
126 : */
127 : operator bool_t() const { return _ptr == 0 ? 0 : &RefPtr::_ptr; }
128 : /** @return true if the RefPtr is empty. @version 1.0 */
129 : bool operator!() const { return (_ptr == 0); }
130 : /**
131 : * @return true if the left RefPtr is smaller then the right.
132 : * @version 1.0
133 : */
134 : bool operator<(const RefPtr& rhs) const { return (_ptr < rhs._ptr); }
135 : /**
136 : * @return true if the right RefPtr is smaller then the left.
137 : * @version 1.0
138 : */
139 : bool operator>(const RefPtr& rhs) const { return (_ptr > rhs._ptr); }
140 : /**
141 : * @return true if the reference pointers holds the C pointer.
142 : * @version 1.0
143 : */
144 : bool operator==(const T* ptr) const { return (_ptr == ptr); }
145 : /**
146 : * @return true if the reference pointers does not hold the C pointer
147 : * @version 1.0
148 : */
149 : bool operator!=(const T* ptr) const { return (_ptr != ptr); }
150 : /** Access the held object. @version 1.0 */
151 12 : T* operator->()
152 : {
153 12 : LBASSERTINFO(_ptr, className(this));
154 12 : return _ptr;
155 : }
156 : /** Access the held object. @version 1.0 */
157 3 : const T* operator->() const
158 : {
159 3 : LBASSERTINFO(_ptr, className(this));
160 3 : return _ptr;
161 : }
162 : /** Access the held object. @version 1.0 */
163 : T& operator*()
164 : {
165 : LBASSERTINFO(_ptr, className(this));
166 : return *_ptr;
167 : }
168 : /** Access the held object. @version 1.0 */
169 : const T& operator*() const
170 : {
171 : LBASSERTINFO(_ptr, className(this));
172 : return *_ptr;
173 : }
174 :
175 : /** @return the C pointer. @version 1.0 */
176 7 : T* get() { return _ptr; }
177 : /** @return the C pointer. @version 1.0 */
178 4 : const T* get() const { return _ptr; }
179 : /** @return true if the RefPtr holds a non-0 pointer. @version 1.0 */
180 : bool isValid() const { return (_ptr != 0); }
181 : private:
182 : T* _ptr;
183 :
184 : /** Artificially reference the held object. */
185 10137812 : void _ref()
186 : {
187 10137812 : if (_ptr)
188 8997941 : _ptr->ref(this);
189 10227801 : }
190 :
191 : /** Artificially dereference the held object. */
192 5000039 : void _unref()
193 : {
194 5000039 : if (_ptr)
195 : {
196 : #ifdef NDEBUG
197 : _ptr->unref(this);
198 : #else
199 5000014 : if (_ptr->unref(this))
200 2000007 : _ptr = 0;
201 : #endif
202 : }
203 5000039 : }
204 : };
205 :
206 : /** Print the reference pointer to the given output stream. */
207 : template <class T>
208 : inline std::ostream& operator<<(std::ostream& os, RefPtr<T> rp)
209 : {
210 : const T* p = rp.get();
211 : if (!p)
212 : return os << "RP[ 0:NULL ]";
213 :
214 : os << disableFlush << "RP[" << p->getRefCount() << ":" << *p << "]";
215 : p->printHolders(os);
216 : return os << enableFlush;
217 : }
218 :
219 : template <class T>
220 0 : inline std::string className(const RefPtr<T>& rp)
221 : {
222 0 : return className(rp.get());
223 : }
224 : }
225 :
226 : #include <boost/serialization/split_free.hpp>
227 :
228 : namespace boost
229 : {
230 : namespace serialization
231 : {
232 : template <class Archive, class T>
233 : inline void save(Archive& ar, const lunchbox::RefPtr<T>& t,
234 : const unsigned int /*version*/)
235 : {
236 : const T* ptr = t.get();
237 : ar << ptr;
238 : }
239 :
240 : template <class Archive, class T>
241 : inline void load(Archive& ar, lunchbox::RefPtr<T>& t,
242 : const unsigned int /*version*/)
243 : {
244 : T* obj = 0;
245 : ar >> obj;
246 : t = obj;
247 : }
248 :
249 : template <class Archive, class T>
250 : inline void serialize(Archive& ar, lunchbox::RefPtr<T>& t,
251 : const unsigned int version)
252 : {
253 : boost::serialization::split_free(ar, t, version);
254 : }
255 : }
256 : }
257 :
258 : #endif // LUNCHBOX_REFPTR_H
|