Fawkes API  Fawkes Development Version
refptr.h
1 
2 /***************************************************************************
3  * refptr.h - reference counting shared smartpointer
4  *
5  * Created: Sat Jan 24 12:29:41 2009
6  * Copyright 2002 The gtkmm Development Team
7  * 2005 The cairomm Development Team
8  * 2009 Tim Niemueller [www.niemueller.de]
9  *
10  ****************************************************************************/
11 
12 /* This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version. A runtime exception applies to
16  * this software (see LICENSE.GPL_WRE file mentioned below for details).
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU Library General Public License for more details.
22  *
23  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
24  */
25 
26 #ifndef __CORE_UTILS_REFPTR_H_
27 #define __CORE_UTILS_REFPTR_H_
28 
29 #include <core/threading/mutex.h>
30 
31 namespace fawkes {
32 
33 /** RefPtr<> is a reference-counting shared smartpointer.
34  *
35  * Reference counting means that a shared reference count is incremented each
36  * time a RefPtr is copied, and decremented each time a RefPtr is destroyed,
37  * for instance when it leaves its scope. When the reference count reaches
38  * zero, the contained object is deleted
39  *
40  * Fawkes uses RefPtr so that you don't need to remember
41  * to delete the object explicitly, or know when a method expects you to delete
42  * the object that it returns.
43  *
44  * Note that RefPtr is thread-safe.
45  *
46  * @ingroup FCL
47  */
48 template <class T_CppObject>
49 class RefPtr
50 {
51  public:
52  /** Default constructor
53  *
54  * Afterwards it will be null and use of -> will cause a segmentation fault.
55  */
56  inline RefPtr();
57 
58  /// Destructor - decrements reference count.
59  inline ~RefPtr();
60 
61  /** Constructor that takes ownership.
62  *
63  * This takes ownership of @a cpp_object, so it will be deleted when the
64  * last RefPtr is deleted, for instance when it goes out of scope.
65  * @param cpp_object C++ object to take ownership of
66  */
67  explicit inline RefPtr(T_CppObject* cpp_object);
68 
69  /** Copy constructor
70  * This increments the shared reference count.
71  * @param src refptr to copy
72  */
73  inline RefPtr(const RefPtr<T_CppObject>& src);
74 
75  /** Copy constructor (from different, but castable type).
76  * Increments the reference count.
77  * @param src refptr to copy
78  */
79  template <class T_CastFrom>
80  inline RefPtr(const RefPtr<T_CastFrom>& src);
81 
82  /** Swap the contents of two RefPtr<>.
83  * This method swaps the internal pointers to T_CppObject. This can be
84  * done safely without involving a reference/unreference cycle and is
85  * therefore highly efficient.
86  * @param other other instance to swap with.
87  */
88  inline void swap(RefPtr<T_CppObject>& other);
89 
90  /** Copy from another RefPtr.
91  * @param src refptr to copy from
92  * @return reference to this instance
93  */
95 
96  /** Copy from different, but castable type).
97  * Increments the reference count.
98  * @param src refptr to copy from
99  * @return reference to this instance
100  */
101  template <class T_CastFrom>
103 
104  /** Assign object and claim ownership.
105  * @param ptr pointer to object, this refptr will claim ownership of the src!
106  * @return reference to this instance
107  */
108  inline RefPtr<T_CppObject>& operator=(T_CppObject *ptr);
109 
110 
111  /** Tests whether the RefPtr<> point to the same underlying instance.
112  * @param src refptr to compare to
113  * @return true if both refptrs point to the same instance.
114  */
115  inline bool operator==(const RefPtr<T_CppObject>& src) const;
116 
117  /** Tests whether the RefPtr<> do not point to the same underlying instance.
118  * @param src refptr to compare to
119  * @return true if both refptrs do not point to the same instance.
120  */
121  inline bool operator!=(const RefPtr<T_CppObject>& src) const;
122 
123  /** Dereferencing.
124  * Use the methods of the underlying instance like so:
125  * <code>refptr->memberfun()</code>.
126  * @return pointer to encapsulated object
127  */
128  inline T_CppObject* operator->() const;
129 
130  /** Get underlying pointer.
131  * Use with care!
132  * @return pointer to encapsulated object
133  */
134  inline T_CppObject* operator*() const;
135 
136 
137  /** Test whether the RefPtr<> points to any underlying instance.
138  *
139  * Mimics usage of ordinary pointers:
140  * @code
141  * if (ptr)
142  * do_something();
143  * @endcode
144  */
145  inline operator bool() const;
146 
147  /// Set underlying instance to 0, decrementing reference count of existing instance appropriately.
148  inline void clear();
149 
150  /** Reset pointer.
151  * Set underlying instance to 0, decrementing reference count of
152  * existing instance appropriately.
153  */
154  inline void reset();
155 
156 
157  /** Dynamic cast to derived class.
158  *
159  * The RefPtr can't be cast with the usual notation so instead you can use
160  * @code
161  * ptr_derived = RefPtr<Derived>::cast_dynamic(ptr_base);
162  * @endcode
163  * @param src source refptr to cast
164  * @return refptr to object casted to given type
165  */
166  template <class T_CastFrom>
168  {
169  T_CppObject *const cpp_object = dynamic_cast<T_CppObject*>(src.operator->());
170 
171  if(cpp_object) //Check whether dynamic_cast<> succeeded so we don't pass a null object with a used refcount:
172  return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
173  else
174  return RefPtr<T_CppObject>();
175  }
176 
177  /** Static cast to derived class.
178  *
179  * Like the dynamic cast; the notation is
180  * @code
181  * ptr_derived = RefPtr<Derived>::cast_static(ptr_base);
182  * @endcode
183  * @param src source refptr to cast
184  * @return refptr to object casted to given type
185  */
186  template <class T_CastFrom>
188  {
189  T_CppObject *const cpp_object = static_cast<T_CppObject*>(src.operator->());
190 
191  return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
192  }
193 
194  /** Cast to non-const.
195  *
196  * The RefPtr can't be cast with the usual notation so instead you can use
197  * @code
198  * ptr_unconst = RefPtr<UnConstType>::cast_const(ptr_const);
199  * @endcode
200  * @param src source refptr to cast
201  * @return refptr to object casted to given type
202  */
203  template <class T_CastFrom>
205  {
206  T_CppObject *const cpp_object = const_cast<T_CppObject*>(src.operator->());
207 
208  return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
209  }
210 
211  /** For use only in the internal implementation of sharedptr.
212  * @param cpp_object C++ object to wrap
213  * @param refcount reference count
214  * @param refmutex reference count mutex
215  */
216  explicit inline RefPtr(T_CppObject *cpp_object, int *refcount, Mutex *refmutex);
217 
218  /** For use only in the internal implementation of sharedptr.
219  * Get reference count pointer.
220  * Warning: This is for internal use only. Do not manually modify the
221  * reference count with this pointer.
222  * @return pointer to refcount integer
223  */
224  inline int * refcount_ptr() const { return __ref_count; }
225 
226  /** Get current reference count.
227  * @return current number of owners referencing this RefPtr.
228  */
229  inline int use_count() const { return *__ref_count; }
230 
231  /** For use only in the internal implementation of sharedptr.
232  * Get reference mutex.
233  * @return pointer to refcount mutex
234  */
235  inline Mutex * refmutex_ptr() const { return __ref_mutex; }
236 
237 private:
238 
239  T_CppObject *__cpp_object;
240  mutable int *__ref_count;
241  mutable Mutex *__ref_mutex;
242 
243 };
244 
245 
246 // RefPtr<>::operator->() comes first here since it's used by other methods.
247 // If it would come after them it wouldn't be inlined.
248 
249 template <class T_CppObject> inline
251 {
252  return __cpp_object;
253 }
254 
255 
256 template <class T_CppObject> inline
257 T_CppObject* RefPtr<T_CppObject>::operator*() const
258 {
259  return __cpp_object;
260 }
261 
262 template <class T_CppObject> inline
264 :
265  __cpp_object(0),
266  __ref_count(0),
267  __ref_mutex(0)
268 {}
269 
270 template <class T_CppObject> inline
272 {
273  if(__ref_count && __ref_mutex)
274  {
275  __ref_mutex->lock();
276 
277  --(*__ref_count);
278 
279  if(*__ref_count == 0)
280  {
281  if(__cpp_object)
282  {
283  delete __cpp_object;
284  __cpp_object = 0;
285  }
286 
287  delete __ref_count;
288  delete __ref_mutex;
289  __ref_count = 0;
290  __ref_mutex = 0;
291  } else {
292  __ref_mutex->unlock();
293  }
294  }
295 }
296 
297 
298 template <class T_CppObject> inline
299 RefPtr<T_CppObject>::RefPtr(T_CppObject* cpp_object)
300 :
301  __cpp_object(cpp_object),
302  __ref_count(0),
303  __ref_mutex(0)
304 {
305  if(cpp_object)
306  {
307  __ref_count = new int;
308  __ref_mutex = new Mutex();
309  *__ref_count = 1; //This will be decremented in the destructor.
310  }
311 }
312 
313 //Used by cast_*() implementations:
314 template <class T_CppObject> inline
315  RefPtr<T_CppObject>::RefPtr(T_CppObject* cpp_object, int* refcount, Mutex *refmutex)
316 :
317  __cpp_object(cpp_object),
318  __ref_count(refcount),
319  __ref_mutex(refmutex)
320 {
321  if(__cpp_object && __ref_count && __ref_mutex) {
322  __ref_mutex->lock();
323  ++(*__ref_count);
324  __ref_mutex->unlock();
325  }
326 }
327 
328 template <class T_CppObject> inline
330 :
331  __cpp_object (src.__cpp_object),
332  __ref_count(src.__ref_count),
333  __ref_mutex(src.__ref_mutex)
334 {
335  if(__cpp_object && __ref_count && __ref_mutex)
336  {
337  __ref_mutex->lock();
338  ++(*__ref_count);
339  __ref_mutex->unlock();
340  }
341 }
342 
343 // The templated ctor allows copy construction from any object that's
344 // castable. Thus, it does downcasts:
345 // base_ref = derived_ref
346 template <class T_CppObject>
347  template <class T_CastFrom>
348 inline
350 :
351  // A different RefPtr<> will not allow us access to __cpp_object. We need
352  // to add a get_underlying() for this, but that would encourage incorrect
353  // use, so we use the less well-known operator->() accessor:
354  __cpp_object (src.operator->()),
355  __ref_count(src.refcount_ptr()),
356  __ref_mutex(src.refmutex_ptr())
357 {
358  if(__cpp_object && __ref_count && __ref_mutex) {
359  __ref_mutex->lock();
360  ++(*__ref_count);
361  __ref_mutex->unlock();
362  }
363 }
364 
365 template <class T_CppObject> inline
366 void
368 {
369  T_CppObject *const temp = __cpp_object;
370  int *temp_count = __ref_count;
371  Mutex *temp_mutex = __ref_mutex;
372 
373  __cpp_object = other.__cpp_object;
374  __ref_count = other.__ref_count;
375  __ref_mutex = other.__ref_mutex;
376 
377  other.__cpp_object = temp;
378  other.__ref_count = temp_count;
379  other.__ref_mutex = temp_mutex;
380 }
381 
382 template <class T_CppObject> inline
385 {
386  // In case you haven't seen the swap() technique to implement copy
387  // assignment before, here's what it does:
388  //
389  // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
390  // increasing the reference count of the source object.
391  //
392  // 2) Swap the internal object pointers of *this and the temporary
393  // RefPtr<>. After this step, *this already contains the new pointer,
394  // and the old pointer is now managed by temp.
395  //
396  // 3) The destructor of temp is executed, thereby unreferencing the
397  // old object pointer.
398  //
399  // This technique is described in Herb Sutter's "Exceptional C++", and
400  // has a number of advantages over conventional approaches:
401  //
402  // - Code reuse by calling the copy ctor.
403  // - Strong exception safety for free.
404  // - Self assignment is handled implicitely.
405  // - Simplicity.
406  // - It just works and is hard to get wrong; i.e. you can use it without
407  // even thinking about it to implement copy assignment whereever the
408  // object data is managed indirectly via a pointer, which is very common.
409 
410  RefPtr<T_CppObject> temp (src);
411  this->swap(temp);
412  return *this;
413 }
414 
415 template <class T_CppObject> inline
418 {
419  RefPtr<T_CppObject> temp(ptr);
420  this->swap(temp);
421  return *this;
422 }
423 
424 
425 template <class T_CppObject>
426  template <class T_CastFrom>
427 inline
430 {
431  RefPtr<T_CppObject> temp (src);
432  this->swap(temp);
433  return *this;
434 }
435 
436 template <class T_CppObject> inline
437 bool
439 {
440  return (__cpp_object == src.__cpp_object);
441 }
442 
443 template <class T_CppObject> inline
444 bool
446 {
447  return (__cpp_object != src.__cpp_object);
448 }
449 
450 template <class T_CppObject> inline
452 {
453  return (__cpp_object != 0);
454 }
455 
456 template <class T_CppObject> inline
458 {
459  RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
460  this->swap(temp);
461 }
462 
463 template <class T_CppObject> inline
465 {
466  RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
467  this->swap(temp);
468 }
469 
470 
471 /** Swap refptr instances.
472  * @param lrp "left" refptr
473  * @param rrp "right" refptr
474  * @relates fawkes::RefPtr
475  */
476 template <class T_CppObject> inline
477 void
479 {
480  lrp.swap(rrp);
481 }
482 
483 } // end namespace fawkes
484 
485 
486 #endif
static RefPtr< T_CppObject > cast_dynamic(const RefPtr< T_CastFrom > &src)
Dynamic cast to derived class.
Definition: refptr.h:167
void swap(RefPtr< T_CppObject > &lrp, RefPtr< T_CppObject > &rrp)
Swap refptr instances.
Definition: refptr.h:478
int * refcount_ptr() const
For use only in the internal implementation of sharedptr.
Definition: refptr.h:224
Fawkes library namespace.
T_CppObject * operator*() const
Get underlying pointer.
Definition: refptr.h:257
RefPtr< T_CppObject > & operator=(const RefPtr< T_CppObject > &src)
Copy from another RefPtr.
Definition: refptr.h:384
Mutex * refmutex_ptr() const
For use only in the internal implementation of sharedptr.
Definition: refptr.h:235
void reset()
Reset pointer.
Definition: refptr.h:464
void clear()
Set underlying instance to 0, decrementing reference count of existing instance appropriately.
Definition: refptr.h:457
void swap(RefPtr< T_CppObject > &other)
Swap the contents of two RefPtr<>.
Definition: refptr.h:367
static RefPtr< T_CppObject > cast_const(const RefPtr< T_CastFrom > &src)
Cast to non-const.
Definition: refptr.h:204
int use_count() const
Get current reference count.
Definition: refptr.h:229
~RefPtr()
Destructor - decrements reference count.
Definition: refptr.h:271
bool operator!=(const RefPtr< T_CppObject > &src) const
Tests whether the RefPtr<> do not point to the same underlying instance.
Definition: refptr.h:445
RefPtr<> is a reference-counting shared smartpointer.
Definition: refptr.h:49
T_CppObject * operator->() const
Dereferencing.
Definition: refptr.h:250
Mutex mutual exclusion lock.
Definition: mutex.h:32
bool operator==(const RefPtr< T_CppObject > &src) const
Tests whether the RefPtr<> point to the same underlying instance.
Definition: refptr.h:438
RefPtr()
Default constructor.
Definition: refptr.h:263
static RefPtr< T_CppObject > cast_static(const RefPtr< T_CastFrom > &src)
Static cast to derived class.
Definition: refptr.h:187