Fawkes API  Fawkes Development Version
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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>
167  static inline RefPtr<T_CppObject> cast_dynamic(const RefPtr<T_CastFrom>& src);
168 
169  /** Static cast to derived class.
170  *
171  * Like the dynamic cast; the notation is
172  * @code
173  * ptr_derived = RefPtr<Derived>::cast_static(ptr_base);
174  * @endcode
175  * @param src source refptr to cast
176  * @return refptr to object casted to given type
177  */
178  template <class T_CastFrom>
179  static inline RefPtr<T_CppObject> cast_static(const RefPtr<T_CastFrom>& src);
180 
181  /** Cast to non-const.
182  *
183  * The RefPtr can't be cast with the usual notation so instead you can use
184  * @code
185  * ptr_unconst = RefPtr<UnConstType>::cast_const(ptr_const);
186  * @endcode
187  * @param src source refptr to cast
188  * @return refptr to object casted to given type
189  */
190  template <class T_CastFrom>
191  static inline RefPtr<T_CppObject> cast_const(const RefPtr<T_CastFrom>& src);
192 
193  /** For use only in the internal implementation of sharedptr.
194  * @param cpp_object C++ object to wrap
195  * @param refcount reference count
196  * @param refmutex reference count mutex
197  */
198  explicit inline RefPtr(T_CppObject *cpp_object, int *refcount, Mutex *refmutex);
199 
200  /** For use only in the internal implementation of sharedptr.
201  * Get reference count pointer.
202  * Warning: This is for internal use only. Do not manually modify the
203  * reference count with this pointer.
204  * @return pointer to refcount integer
205  */
206  inline int * refcount_ptr() const { return __ref_count; }
207 
208  /** Get current reference count.
209  * @return current number of owners referencing this RefPtr.
210  */
211  inline int use_count() const { return *__ref_count; }
212 
213  /** For use only in the internal implementation of sharedptr.
214  * Get reference mutex.
215  * @return pointer to refcount mutex
216  */
217  inline Mutex * refmutex_ptr() const { return __ref_mutex; }
218 
219 private:
220 
221  T_CppObject *__cpp_object;
222  mutable int *__ref_count;
223  mutable Mutex *__ref_mutex;
224 
225 };
226 
227 
228 // RefPtr<>::operator->() comes first here since it's used by other methods.
229 // If it would come after them it wouldn't be inlined.
230 
231 template <class T_CppObject> inline
233 {
234  return __cpp_object;
235 }
236 
237 
238 template <class T_CppObject> inline
239 T_CppObject* RefPtr<T_CppObject>::operator*() const
240 {
241  return __cpp_object;
242 }
243 
244 template <class T_CppObject> inline
246 :
247  __cpp_object(0),
248  __ref_count(0),
249  __ref_mutex(0)
250 {}
251 
252 template <class T_CppObject> inline
254 {
255  if(__ref_count && __ref_mutex)
256  {
257  __ref_mutex->lock();
258 
259  --(*__ref_count);
260 
261  if(*__ref_count == 0)
262  {
263  if(__cpp_object)
264  {
265  delete __cpp_object;
266  __cpp_object = 0;
267  }
268 
269  delete __ref_count;
270  delete __ref_mutex;
271  __ref_count = 0;
272  __ref_mutex = 0;
273  } else {
274  __ref_mutex->unlock();
275  }
276  }
277 }
278 
279 
280 template <class T_CppObject> inline
281 RefPtr<T_CppObject>::RefPtr(T_CppObject* cpp_object)
282 :
283  __cpp_object(cpp_object),
284  __ref_count(0),
285  __ref_mutex(0)
286 {
287  if(cpp_object)
288  {
289  __ref_count = new int;
290  __ref_mutex = new Mutex();
291  *__ref_count = 1; //This will be decremented in the destructor.
292  }
293 }
294 
295 //Used by cast_*() implementations:
296 template <class T_CppObject> inline
297  RefPtr<T_CppObject>::RefPtr(T_CppObject* cpp_object, int* refcount, Mutex *refmutex)
298 :
299  __cpp_object(cpp_object),
300  __ref_count(refcount),
301  __ref_mutex(refmutex)
302 {
303  if(__cpp_object && __ref_count && __ref_mutex) {
304  __ref_mutex->lock();
305  ++(*__ref_count);
306  __ref_mutex->unlock();
307  }
308 }
309 
310 template <class T_CppObject> inline
312 :
313  __cpp_object (src.__cpp_object),
314  __ref_count(src.__ref_count),
315  __ref_mutex(src.__ref_mutex)
316 {
317  if(__cpp_object && __ref_count && __ref_mutex)
318  {
319  __ref_mutex->lock();
320  ++(*__ref_count);
321  __ref_mutex->unlock();
322  }
323 }
324 
325 // The templated ctor allows copy construction from any object that's
326 // castable. Thus, it does downcasts:
327 // base_ref = derived_ref
328 template <class T_CppObject>
329  template <class T_CastFrom>
330 inline
332 :
333  // A different RefPtr<> will not allow us access to __cpp_object. We need
334  // to add a get_underlying() for this, but that would encourage incorrect
335  // use, so we use the less well-known operator->() accessor:
336  __cpp_object (src.operator->()),
337  __ref_count(src.refcount_ptr()),
338  __ref_mutex(src.refmutex_ptr())
339 {
340  if(__cpp_object && __ref_count && __ref_mutex) {
341  __ref_mutex->lock();
342  ++(*__ref_count);
343  __ref_mutex->unlock();
344  }
345 }
346 
347 template <class T_CppObject> inline
348 void
350 {
351  T_CppObject *const temp = __cpp_object;
352  int *temp_count = __ref_count;
353  Mutex *temp_mutex = __ref_mutex;
354 
355  __cpp_object = other.__cpp_object;
356  __ref_count = other.__ref_count;
357  __ref_mutex = other.__ref_mutex;
358 
359  other.__cpp_object = temp;
360  other.__ref_count = temp_count;
361  other.__ref_mutex = temp_mutex;
362 }
363 
364 template <class T_CppObject> inline
367 {
368  // In case you haven't seen the swap() technique to implement copy
369  // assignment before, here's what it does:
370  //
371  // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
372  // increasing the reference count of the source object.
373  //
374  // 2) Swap the internal object pointers of *this and the temporary
375  // RefPtr<>. After this step, *this already contains the new pointer,
376  // and the old pointer is now managed by temp.
377  //
378  // 3) The destructor of temp is executed, thereby unreferencing the
379  // old object pointer.
380  //
381  // This technique is described in Herb Sutter's "Exceptional C++", and
382  // has a number of advantages over conventional approaches:
383  //
384  // - Code reuse by calling the copy ctor.
385  // - Strong exception safety for free.
386  // - Self assignment is handled implicitely.
387  // - Simplicity.
388  // - It just works and is hard to get wrong; i.e. you can use it without
389  // even thinking about it to implement copy assignment whereever the
390  // object data is managed indirectly via a pointer, which is very common.
391 
392  RefPtr<T_CppObject> temp (src);
393  this->swap(temp);
394  return *this;
395 }
396 
397 template <class T_CppObject> inline
400 {
401  RefPtr<T_CppObject> temp(ptr);
402  this->swap(temp);
403  return *this;
404 }
405 
406 
407 template <class T_CppObject>
408  template <class T_CastFrom>
409 inline
412 {
413  RefPtr<T_CppObject> temp (src);
414  this->swap(temp);
415  return *this;
416 }
417 
418 template <class T_CppObject> inline
419 bool
421 {
422  return (__cpp_object == src.__cpp_object);
423 }
424 
425 template <class T_CppObject> inline
426 bool
428 {
429  return (__cpp_object != src.__cpp_object);
430 }
431 
432 template <class T_CppObject> inline
434 {
435  return (__cpp_object != 0);
436 }
437 
438 template <class T_CppObject> inline
440 {
441  RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
442  this->swap(temp);
443 }
444 
445 template <class T_CppObject> inline
447 {
448  RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
449  this->swap(temp);
450 }
451 
452 template <class T_CppObject>
453  template <class T_CastFrom>
454 inline
457 {
458  T_CppObject *const cpp_object = dynamic_cast<T_CppObject*>(src.operator->());
459 
460  if(cpp_object) //Check whether dynamic_cast<> succeeded so we don't pass a null object with a used refcount:
461  return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
462  else
463  return RefPtr<T_CppObject>();
464 }
465 
466 template <class T_CppObject>
467  template <class T_CastFrom>
468 inline
471 {
472  T_CppObject *const cpp_object = static_cast<T_CppObject*>(src.operator->());
473 
474  return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
475 }
476 
477 template <class T_CppObject>
478  template <class T_CastFrom>
479 inline
482 {
483  T_CppObject *const cpp_object = const_cast<T_CppObject*>(src.operator->());
484 
485  return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
486 }
487 
488 
489 /** Swap refptr instances.
490  * @param lrp "left" refptr
491  * @param rrp "right" refptr
492  * @relates fawkes::RefPtr
493  */
494 template <class T_CppObject> inline
495 void
497 {
498  lrp.swap(rrp);
499 }
500 
501 } // end namespace fawkes
502 
503 
504 #endif
void swap(RefPtr< T_CppObject > &lrp, RefPtr< T_CppObject > &rrp)
Swap refptr instances.
Definition: refptr.h:496
void unlock()
Unlock the mutex.
Definition: mutex.cpp:135
int * refcount_ptr() const
For use only in the internal implementation of sharedptr.
Definition: refptr.h:206
bool operator!=(const RefPtr< T_CppObject > &src) const
Tests whether the RefPtr&lt;&gt; do not point to the same underlying instance.
Definition: refptr.h:427
static RefPtr< T_CppObject > cast_static(const RefPtr< T_CastFrom > &src)
Static cast to derived class.
Definition: refptr.h:470
RefPtr< T_CppObject > & operator=(const RefPtr< T_CppObject > &src)
Copy from another RefPtr.
Definition: refptr.h:366
T_CppObject * operator->() const
Dereferencing.
Definition: refptr.h:232
void reset()
Reset pointer.
Definition: refptr.h:446
void clear()
Set underlying instance to 0, decrementing reference count of existing instance appropriately.
Definition: refptr.h:439
void swap(RefPtr< T_CppObject > &other)
Swap the contents of two RefPtr&lt;&gt;.
Definition: refptr.h:349
Mutex * refmutex_ptr() const
For use only in the internal implementation of sharedptr.
Definition: refptr.h:217
static RefPtr< T_CppObject > cast_dynamic(const RefPtr< T_CastFrom > &src)
Dynamic cast to derived class.
Definition: refptr.h:456
~RefPtr()
Destructor - decrements reference count.
Definition: refptr.h:253
static RefPtr< T_CppObject > cast_const(const RefPtr< T_CastFrom > &src)
Cast to non-const.
Definition: refptr.h:481
bool operator==(const RefPtr< T_CppObject > &src) const
Tests whether the RefPtr&lt;&gt; point to the same underlying instance.
Definition: refptr.h:420
RefPtr&lt;&gt; is a reference-counting shared smartpointer.
Definition: refptr.h:49
void lock()
Lock this mutex.
Definition: mutex.cpp:89
Mutex mutual exclusion lock.
Definition: mutex.h:32
int use_count() const
Get current reference count.
Definition: refptr.h:211
RefPtr()
Default constructor.
Definition: refptr.h:245
T_CppObject * operator*() const
Get underlying pointer.
Definition: refptr.h:239