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