openModeller  Version 1.5.0
refcount.hh
Go to the documentation of this file.
1 #ifndef _REFCOUNT_HH
2 #define _REFCOUNT_HH
3 
4 #include <openmodeller/Log.hh>
5 
6 #undef DEBUG_MEMORY
7 
8 //
9 // This is a very small templated TypeTraits class which really only
10 // provides a convient way to strip const qualifiers. It is needed
11 // by the ReferenceCountedPointer<> template below to create
12 // ReferenceCountedPointer< const T * >. Without the PlainPointerType,
13 // the underlying type would be const T* instead of the correct
14 // T*.
15 //
16 template< typename T >
17 class TypeTraits {
18 private:
19  template< class U > struct UnConst
20  {
21  typedef U* PointerType;
22  typedef U* PlainPointerType;
23  typedef U& ReferenceType;
24  typedef U& PlainReferenceType;
25  };
26  template< class U > struct UnConst<const U> {
27  typedef U const * PointerType;
28  typedef U* PlainPointerType;
29  typedef const U & ReferenceType;
30  typedef U& PlainReferenceType;
31  };
32 public:
33  typedef typename UnConst<T>::PointerType PointerType;
34  typedef typename UnConst<T>::ReferenceType ReferenceType;
35  typedef typename UnConst<T>::PlainPointerType PlainPointerType;
36 };
37 
38 //
39 // Declaration of ReferenceCountedObject.
40 //
41 // This class contains the _ref_count and is used to decorate
42 // objects which ReferenceCountedPointer points to.
43 // This is an intrusive reference count (you need to derive from
44 // this class). This mechanism has been chosen because
45 // we have the source of the library and can change the code
46 // to derive from this class, and it's space and runtime overhead
47 // is minimal.
48 //
50 {
51 
52  /* I'd like to get friendship to work here */
53  /* Instead each derived class from this base needs
54  To have it's container's class declared a friend */
55  template< typename T >
57 
58 protected:
60  _ref_count(0)
61  {}
62 
63  virtual inline ~ReferenceCountedObject() = 0;
64 
65 private:
66 
68 
69 };
70 
71 template< class T >
73 public:
74 
78 
79  template< typename S >
81 
82  //
83  // Default constructor creates pointer to null.
84  inline ReferenceCountedPointer( );
85 
86  //
87  // implict conversion constructor from T*.
88  // Provides for the following syntax
89  // ReferenceCountedPointer<T> ptr = new T();
90  // ... ReferenceCountedPoitner<T> ( new T() );
91  //
93  //
94  // Conversion from class S derived from T
95  template< class S >
96  inline ReferenceCountedPointer( S* );
97 
98  //
99  // copy constructor.
101  //
102  // copy constructor from derived classes
103  template< class S >
105 
106  //
107  // destructor
108  inline virtual ~ReferenceCountedPointer();
109 
110  inline ReferenceType operator*() const;
111  inline PointerType operator->() const;
112 
113  //
114  // Assignment operator.
116  template< class S >
118 
119  //
120  // Assignment from plain pointer classes.
122  template< class S >
123  inline ReferenceCountedPointer<T>& operator=( S*& );
124 
125  // Two ways to test for NULL-ness.
126  inline bool operator!() const;
127  inline operator bool() const;
128 
129  // Need a member for swap since VC doesn't allow friend templates
130  inline void swap( ReferenceCountedPointer<T>& rhs) {
131  PlainPointerType tmp = this->_p;
132  this->_p = rhs._p;
133  rhs._p = tmp;
134  }
135 
136 private:
137  inline void releasePointer();
138  inline void takePointer( PlainPointerType ptr );
139 
141 
142 };
143 
144 template< class T >
145 void
147  lhs.swap(rhs);
148 }
149 
150 /*
151  *
152  * Implementation for ReferenceCountedPointer inlines
153  *
154  */
155 template< class T >
157  _p( 0 )
158 {
159 # if defined(DEBUG_MEMORY)
160  Log::instance()->debug( "ReferenceCountedPointer<T>::ReferenceCountedPointer()\n");
161 # endif
162 }
163 
164 template< class T >
166 {
167 # if defined(DEBUG_MEMORY)
168  Log::instance()->debug( "ReferenceCountedPointer<T>::ReferenceCountedPointer( const ReferenceCountedPointer & rhs )\n" );
169 # endif
170  takePointer( rhs._p );
171 }
172 
173 template< class T >
174 template< class S >
176 {
177 # if defined(DEBUG_MEMORY)
178  Log::instance()->debug( "ReferenceCountedPointer<T>::ReferenceCountedPointer( const ReferenceCountedPointer<S> & rhs )\n" );
179 # endif
180  takePointer( rhs._p );
181 }
182 
183 template< class T >
185 {
186 # if defined(DEBUG_MEMORY)
187  Log::instance()->debug( "ReferenceCountedPointer<T>::ReferenceCountedPointer( T* rhs )\n" );
188 # endif
189  takePointer( rhs );
190 }
191 
192 template< class T >
193 template< class S >
195 {
196 # if defined(DEBUG_MEMORY)
197  Log::instance()->debug( "ReferenceCountedPointer<T>::ReferenceCountedPointer( S* rhs )\n" );
198 # endif
199  takePointer( rhs );
200 }
201 
202 template< class T >
204 {
205 # if defined(DEBUG_MEMORY)
206  Log::instance()->debug( "ReferenceCountedPointer<T>::~ReferenceCountedPointer()\n" );
207 # endif
208  releasePointer();
209 }
210 
211 template< class T >
214 {
215 # if defined(DEBUG_MEMORY)
216  Log::instance()->debug( "ReferenceCountedPointer<T>::operator=( const ReferenceCountedPointer<T>& rhs )\n" );
217 # endif
218  if ( this == &rhs )
219  return *this;
220 
221  if ( this->_p == rhs._p )
222  return *this;
223 
224  releasePointer();
225  takePointer( rhs._p );
226  return *this;
227 }
228 
229 template< class T >
230 template< class S >
233 {
234 # if defined(DEBUG_MEMORY)
235  Log::instance()->debug( "ReferenceCountedPointer<T>::operator=( const ReferenceCountedPointer<S>& rhs )\n" );
236 # endif
237  if ( this == &rhs )
238  return *this;
239 
240  if ( this->_p == rhs._p )
241  return *this;
242 
243  releasePointer();
244  takePointer( rhs._p );
245  return *this;
246 }
247 
248 template< class T >
251 {
252 # if defined(DEBUG_MEMORY)
253  Log::instance()->debug( "ReferenceCountedPointer<T>::operator=( T*& rhs )\n" );
254 # endif
255  if ( this->_p == rhs )
256  return *this;
257 
258  releasePointer();
259  takePointer( rhs );
260  return *this;
261 }
262 
263 template< class T >
264 template< class S >
267 {
268 # if defined(DEBUG_MEMORY)
269  Log::instance()->debug( "ReferenceCountedPointer<T>::operator=( S*& rhs )\n" );
270 # endif
271  if ( this->_p == rhs )
272  return *this;
273 
274  releasePointer();
275  takePointer( rhs );
276  return *this;
277 }
278 
279 template< class T >
282 {
283  return *_p;
284 }
285 
286 template< class T >
289 {
290  return _p;
291 }
292 
293 template< class T >
295 {
296  return (_p == 0);
297 }
298 
299 template< class T >
301 {
302  return (_p != 0);
303 }
304 
305 template< class T >
306 void
308 {
309  if ( _p ) {
310 
311  --_p->_ref_count;
312 
313  if ( _p->_ref_count <= 0 ) {
314  delete _p;
315  _p = 0;
316  }
317  }
318 }
319 
320 template< class T >
321 void
323 {
324 # if defined(DEBUG_MEMORY)
325  Log::instance()->debug( "Taking Pointer: %x\n", ptr );
326 # endif
327  _p = ptr;
328  if ( _p != 0 ) {
329 
330  ++_p->_ref_count;
331 
332 # if defined(DEBUG_MEMORY)
333  Log::instance()->debug( "Recount is: %d\n",_p->_ref_count);
334 # endif
335 
336  }
337 }
338 
340 {}
341 
342 #endif
void swap(ReferenceCountedPointer< T > &lhs, ReferenceCountedPointer< T > &rhs)
Definition: refcount.hh:146
void swap(ReferenceCountedPointer< T > &rhs)
Definition: refcount.hh:130
UnConst< T >::PlainPointerType PlainPointerType
Definition: refcount.hh:35
static Log * instance()
Returns the instance pointer, creating the object on the first call.
Definition: Log.cpp:45
virtual ~ReferenceCountedObject()=0
Definition: refcount.hh:339
UnConst< T >::PointerType PointerType
Definition: refcount.hh:33
PointerType operator->() const
Definition: refcount.hh:288
TypeTraits< T >::PlainPointerType PlainPointerType
Definition: refcount.hh:77
void takePointer(PlainPointerType ptr)
Definition: refcount.hh:322
TypeTraits< T >::PointerType PointerType
Definition: refcount.hh:75
PlainPointerType _p
Definition: refcount.hh:140
TypeTraits< T >::ReferenceType ReferenceType
Definition: refcount.hh:76
UnConst< T >::ReferenceType ReferenceType
Definition: refcount.hh:34
bool operator!() const
Definition: refcount.hh:294
ReferenceCountedPointer< T > & operator=(const ReferenceCountedPointer &)
Definition: refcount.hh:213
ReferenceType operator*() const
Definition: refcount.hh:281
virtual ~ReferenceCountedPointer()
Definition: refcount.hh:203
void debug(const char *format,...)
'Debug' level.
Definition: Log.cpp:237