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 > class RefPtr
40 : {
41 : typedef T* RefPtr::*bool_t;
42 :
43 : public:
44 : /** Construct a new, empty reference pointer. @version 1.0 */
45 25 : RefPtr() : _ptr( 0 ) {}
46 :
47 : /** Construct a reference pointer from a C pointer. @version 1.0 */
48 : // cppcheck-suppress noExplicitConstructor
49 2000007 : RefPtr( T* const ptr ) : _ptr( ptr ) { _ref(); }
50 :
51 : /** Construct a copy of a reference pointer. @version 1.0 */
52 3000007 : RefPtr( const RefPtr& from ) : _ptr( from._ptr ) { _ref(); }
53 :
54 : /**
55 : * Construct a copy of a reference pointer of a different type.
56 : * @version 1.0
57 : */
58 : // cppcheck-suppress noExplicitConstructor
59 : template< class O > RefPtr( RefPtr< O > from )
60 : : _ptr( from.get( )) { _ref(); }
61 :
62 : /** Destruct this reference pointer. @version 1.0 */
63 5000039 : ~RefPtr() { _unref(); _ptr = 0; }
64 :
65 : /** Assign another RefPtr to this reference pointer. @version 1.0 */
66 6584811 : RefPtr& operator = ( const RefPtr& rhs )
67 : {
68 6584811 : if( _ptr == rhs._ptr )
69 3269855 : return *this;
70 :
71 3314956 : T* tmp = _ptr;
72 3314956 : _ptr = rhs._ptr;
73 3314956 : _ref();
74 3144109 : if( tmp ) tmp->unref( this );
75 3989706 : return *this;
76 : }
77 :
78 : /** Assign a C pointer to this reference pointer. @version 1.0 */
79 3460862 : RefPtr& operator = ( T* ptr )
80 : {
81 3460862 : if( _ptr == ptr )
82 0 : return *this;
83 :
84 3460862 : T* tmp = _ptr;
85 3460862 : _ptr = ptr;
86 3460862 : _ref();
87 3455840 : if( tmp ) tmp->unref( this );
88 3732761 : return *this;
89 : }
90 :
91 : /**
92 : * @return true if both reference pointers hold the same C pointer.
93 : * @version 1.0
94 : */
95 : bool operator == ( const RefPtr& rhs ) const
96 : { return ( _ptr == rhs._ptr ); }
97 :
98 : /**
99 : * @return true if both reference pointer hold different C pointer.
100 : * @version 1.0
101 : */
102 : bool operator != ( const RefPtr& rhs ) const
103 : { return ( _ptr != rhs._ptr ); }
104 :
105 : /**
106 : * @return true if a pointer is held, false otherwise.
107 : * @version 1.1.5
108 : */
109 : operator bool_t() const { return _ptr == 0 ? 0 : &RefPtr::_ptr; }
110 :
111 : /** @return true if the RefPtr is empty. @version 1.0 */
112 : bool operator ! () const { return ( _ptr==0 ); }
113 :
114 : /**
115 : * @return true if the left RefPtr is smaller then the right.
116 : * @version 1.0
117 : */
118 : bool operator < ( const RefPtr& rhs ) const { return ( _ptr < rhs._ptr ); }
119 :
120 : /**
121 : * @return true if the right RefPtr is smaller then the left.
122 : * @version 1.0
123 : */
124 : bool operator > ( const RefPtr& rhs ) const { return ( _ptr > rhs._ptr ); }
125 :
126 : /**
127 : * @return true if the reference pointers holds the C pointer.
128 : * @version 1.0
129 : */
130 : bool operator == ( const T* ptr ) const { return ( _ptr == ptr ); }
131 :
132 : /**
133 : * @return true if the reference pointers does not hold the C pointer
134 : * @version 1.0
135 : */
136 : bool operator != ( const T* ptr ) const { return ( _ptr != ptr ); }
137 :
138 : /** Access the held object. @version 1.0 */
139 12 : T* operator->()
140 12 : { LBASSERTINFO( _ptr, className( this )); return _ptr; }
141 : /** Access the held object. @version 1.0 */
142 3 : const T* operator->() const
143 3 : { LBASSERTINFO( _ptr, className( this )); return _ptr; }
144 : /** Access the held object. @version 1.0 */
145 : T& operator*()
146 : { LBASSERTINFO( _ptr, className( this )); return *_ptr; }
147 : /** Access the held object. @version 1.0 */
148 : const T& operator*() const
149 : { LBASSERTINFO( _ptr, className( this )); return *_ptr; }
150 :
151 : /** @return the C pointer. @version 1.0 */
152 7 : T* get() { return _ptr; }
153 : /** @return the C pointer. @version 1.0 */
154 4 : const T* get() const { return _ptr; }
155 :
156 : /** @return true if the RefPtr holds a non-0 pointer. @version 1.0 */
157 : bool isValid() const { return ( _ptr != 0 ); }
158 :
159 : private:
160 : T* _ptr;
161 :
162 : /** Artificially reference the held object. */
163 9449553 : void _ref() { if(_ptr) _ptr->ref( this ); }
164 :
165 : /** Artificially dereference the held object. */
166 5000039 : void _unref()
167 : {
168 5000039 : if(_ptr)
169 : {
170 : #ifdef NDEBUG
171 : _ptr->unref( this );
172 : #else
173 5000014 : if( _ptr->unref( this ))
174 2000007 : _ptr = 0;
175 : #endif
176 : }
177 5000039 : }
178 : };
179 :
180 : /** Print the reference pointer to the given output stream. */
181 : template< class T >
182 : inline std::ostream& operator << ( std::ostream& os, RefPtr< T > rp )
183 : {
184 : const T* p = rp.get();
185 : if( !p )
186 : return os << "RP[ 0:NULL ]";
187 :
188 : os << disableFlush << "RP[" << p->getRefCount() << ":" << *p << "]";
189 : p->printHolders( os );
190 : return os << enableFlush;
191 : }
192 :
193 : template< class T > inline std::string className( const RefPtr<T>& rp )
194 : { return className( rp.get( )); }
195 : }
196 :
197 : #include <boost/serialization/split_free.hpp>
198 :
199 : namespace boost
200 : {
201 : namespace serialization
202 : {
203 :
204 : template< class Archive, class T >
205 : inline void save( Archive& ar, const lunchbox::RefPtr< T >& t,
206 : const unsigned int /*version*/ )
207 : {
208 : const T* ptr = t.get();
209 : ar << ptr;
210 : }
211 :
212 : template< class Archive, class T >
213 : inline void load( Archive& ar, lunchbox::RefPtr< T >& t,
214 : const unsigned int /*version*/ )
215 : {
216 : T* obj = 0;
217 : ar >> obj;
218 : t = obj;
219 : }
220 :
221 : template< class Archive, class T >
222 : inline void serialize( Archive& ar, lunchbox::RefPtr< T >& t,
223 : const unsigned int version )
224 : {
225 : boost::serialization::split_free( ar, t, version );
226 : }
227 :
228 : }
229 : }
230 :
231 : #endif //LUNCHBOX_REFPTR_H
|