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  /** Tests whether the RefPtr<> point to the same underlying instance.
111  * @param src refptr to compare to
112  * @return true if both refptrs point to the same instance.
113  */
114  inline bool operator==(const RefPtr<T_CppObject> &src) const;
115 
116  /** Tests whether the RefPtr<> do not point to the same underlying instance.
117  * @param src refptr to compare to
118  * @return true if both refptrs do not point to the same instance.
119  */
120  inline bool operator!=(const RefPtr<T_CppObject> &src) const;
121 
122  /** Dereferencing.
123  * Use the methods of the underlying instance like so:
124  * <code>refptr->memberfun()</code>.
125  * @return pointer to encapsulated object
126  */
127  inline T_CppObject *operator->() const;
128 
129  /** Get underlying pointer.
130  * Use with care!
131  * @return pointer to encapsulated object
132  */
133  inline T_CppObject *operator*() const;
134 
135  /** Test whether the RefPtr<> points to any underlying instance.
136  *
137  * Mimics usage of ordinary pointers:
138  * @code
139  * if (ptr)
140  * do_something();
141  * @endcode
142  */
143  inline operator bool() const;
144 
145  /// Set underlying instance to 0, decrementing reference count of existing instance appropriately.
146  inline void clear();
147 
148  /** Reset pointer.
149  * Set underlying instance to 0, decrementing reference count of
150  * existing instance appropriately.
151  */
152  inline void reset();
153 
154  /** Dynamic cast to derived class.
155  *
156  * The RefPtr can't be cast with the usual notation so instead you can use
157  * @code
158  * ptr_derived = RefPtr<Derived>::cast_dynamic(ptr_base);
159  * @endcode
160  * @param src source refptr to cast
161  * @return refptr to object casted to given type
162  */
163  template <class T_CastFrom>
164  static inline RefPtr<T_CppObject>
166  {
167  T_CppObject *const cpp_object = dynamic_cast<T_CppObject *>(src.operator->());
168 
169  if (
170  cpp_object) //Check whether dynamic_cast<> succeeded so we don't pass a null object with a used refcount:
171  return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
172  else
173  return RefPtr<T_CppObject>();
174  }
175 
176  /** Static cast to derived class.
177  *
178  * Like the dynamic cast; the notation is
179  * @code
180  * ptr_derived = RefPtr<Derived>::cast_static(ptr_base);
181  * @endcode
182  * @param src source refptr to cast
183  * @return refptr to object casted to given type
184  */
185  template <class T_CastFrom>
186  static inline RefPtr<T_CppObject>
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>
204  static inline RefPtr<T_CppObject>
206  {
207  T_CppObject *const cpp_object = const_cast<T_CppObject *>(src.operator->());
208 
209  return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
210  }
211 
212  /** For use only in the internal implementation of sharedptr.
213  * @param cpp_object C++ object to wrap
214  * @param refcount reference count
215  * @param refmutex reference count mutex
216  */
217  explicit inline RefPtr(T_CppObject *cpp_object, int *refcount, Mutex *refmutex);
218 
219  /** For use only in the internal implementation of sharedptr.
220  * Get reference count pointer.
221  * Warning: This is for internal use only. Do not manually modify the
222  * reference count with this pointer.
223  * @return pointer to refcount integer
224  */
225  inline int *
226  refcount_ptr() const
227  {
228  return ref_count_;
229  }
230 
231  /** Get current reference count.
232  * @return current number of owners referencing this RefPtr.
233  */
234  inline int
235  use_count() const
236  {
237  return *ref_count_;
238  }
239 
240  /** For use only in the internal implementation of sharedptr.
241  * Get reference mutex.
242  * @return pointer to refcount mutex
243  */
244  inline Mutex *
245  refmutex_ptr() const
246  {
247  return ref_mutex_;
248  }
249 
250 private:
251  T_CppObject * cpp_object_;
252  mutable int * ref_count_;
253  mutable Mutex *ref_mutex_;
254 };
255 
256 // RefPtr<>::operator->() comes first here since it's used by other methods.
257 // If it would come after them it wouldn't be inlined.
258 
259 template <class T_CppObject>
260 inline T_CppObject *RefPtr<T_CppObject>::operator->() const
261 {
262  return cpp_object_;
263 }
264 
265 template <class T_CppObject>
266 inline T_CppObject *RefPtr<T_CppObject>::operator*() const
267 {
268  return cpp_object_;
269 }
270 
271 template <class T_CppObject>
272 inline RefPtr<T_CppObject>::RefPtr() : cpp_object_(0), ref_count_(0), ref_mutex_(0)
273 {
274 }
275 
276 template <class T_CppObject>
278 {
279  if (ref_count_ && ref_mutex_) {
280  ref_mutex_->lock();
281 
282  --(*ref_count_);
283 
284  if (*ref_count_ == 0) {
285  if (cpp_object_) {
286  delete cpp_object_;
287  cpp_object_ = 0;
288  }
289 
290  delete ref_count_;
291  delete ref_mutex_;
292  ref_count_ = 0;
293  ref_mutex_ = 0;
294  } else {
295  ref_mutex_->unlock();
296  }
297  }
298 }
299 
300 template <class T_CppObject>
301 inline RefPtr<T_CppObject>::RefPtr(T_CppObject *cpp_object)
302 : cpp_object_(cpp_object), ref_count_(0), ref_mutex_(0)
303 {
304  if (cpp_object) {
305  ref_count_ = new int;
306  ref_mutex_ = new Mutex();
307  *ref_count_ = 1; //This will be decremented in the destructor.
308  }
309 }
310 
311 //Used by cast_*() implementations:
312 template <class T_CppObject>
313 inline RefPtr<T_CppObject>::RefPtr(T_CppObject *cpp_object, int *refcount, Mutex *refmutex)
314 : cpp_object_(cpp_object), ref_count_(refcount), ref_mutex_(refmutex)
315 {
316  if (cpp_object_ && ref_count_ && ref_mutex_) {
317  ref_mutex_->lock();
318  ++(*ref_count_);
319  ref_mutex_->unlock();
320  }
321 }
322 
323 template <class T_CppObject>
325 : cpp_object_(src.cpp_object_), ref_count_(src.ref_count_), ref_mutex_(src.ref_mutex_)
326 {
327  if (cpp_object_ && ref_count_ && ref_mutex_) {
328  ref_mutex_->lock();
329  ++(*ref_count_);
330  ref_mutex_->unlock();
331  }
332 }
333 
334 // The templated ctor allows copy construction from any object that's
335 // castable. Thus, it does downcasts:
336 // base_ref = derived_ref
337 template <class T_CppObject>
338 template <class T_CastFrom>
340 : // A different RefPtr<> will not allow us access to cpp_object_. We need
341  // to add a get_underlying() for this, but that would encourage incorrect
342  // use, so we use the less well-known operator->() accessor:
343  cpp_object_(src.operator->()),
344  ref_count_(src.refcount_ptr()),
345  ref_mutex_(src.refmutex_ptr())
346 {
347  if (cpp_object_ && ref_count_ && ref_mutex_) {
348  ref_mutex_->lock();
349  ++(*ref_count_);
350  ref_mutex_->unlock();
351  }
352 }
353 
354 template <class T_CppObject>
355 inline void
357 {
358  T_CppObject *const temp = cpp_object_;
359  int * temp_count = ref_count_;
360  Mutex * temp_mutex = ref_mutex_;
361 
362  cpp_object_ = other.cpp_object_;
363  ref_count_ = other.ref_count_;
364  ref_mutex_ = other.ref_mutex_;
365 
366  other.cpp_object_ = temp;
367  other.ref_count_ = temp_count;
368  other.ref_mutex_ = temp_mutex;
369 }
370 
371 template <class T_CppObject>
372 inline RefPtr<T_CppObject> &
374 {
375  // In case you haven't seen the swap() technique to implement copy
376  // assignment before, here's what it does:
377  //
378  // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
379  // increasing the reference count of the source object.
380  //
381  // 2) Swap the internal object pointers of *this and the temporary
382  // RefPtr<>. After this step, *this already contains the new pointer,
383  // and the old pointer is now managed by temp.
384  //
385  // 3) The destructor of temp is executed, thereby unreferencing the
386  // old object pointer.
387  //
388  // This technique is described in Herb Sutter's "Exceptional C++", and
389  // has a number of advantages over conventional approaches:
390  //
391  // - Code reuse by calling the copy ctor.
392  // - Strong exception safety for free.
393  // - Self assignment is handled implicitely.
394  // - Simplicity.
395  // - It just works and is hard to get wrong; i.e. you can use it without
396  // even thinking about it to implement copy assignment whereever the
397  // object data is managed indirectly via a pointer, which is very common.
398 
399  RefPtr<T_CppObject> temp(src);
400  this->swap(temp);
401  return *this;
402 }
403 
404 template <class T_CppObject>
405 inline RefPtr<T_CppObject> &
407 {
408  RefPtr<T_CppObject> temp(ptr);
409  this->swap(temp);
410  return *this;
411 }
412 
413 template <class T_CppObject>
414 template <class T_CastFrom>
415 inline RefPtr<T_CppObject> &
417 {
418  RefPtr<T_CppObject> temp(src);
419  this->swap(temp);
420  return *this;
421 }
422 
423 template <class T_CppObject>
424 inline bool
426 {
427  return (cpp_object_ == src.cpp_object_);
428 }
429 
430 template <class T_CppObject>
431 inline bool
433 {
434  return (cpp_object_ != src.cpp_object_);
435 }
436 
437 template <class T_CppObject>
438 inline RefPtr<T_CppObject>::operator bool() const
439 {
440  return (cpp_object_ != 0);
441 }
442 
443 template <class T_CppObject>
444 inline void
446 {
447  RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
448  this->swap(temp);
449 }
450 
451 template <class T_CppObject>
452 inline void
454 {
455  RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
456  this->swap(temp);
457 }
458 
459 /** Swap refptr instances.
460  * @param lrp "left" refptr
461  * @param rrp "right" refptr
462  * @relates fawkes::RefPtr
463  */
464 template <class T_CppObject>
465 inline void
467 {
468  lrp.swap(rrp);
469 }
470 
471 } // end namespace fawkes
472 
473 #endif
static RefPtr< T_CppObject > cast_dynamic(const RefPtr< T_CastFrom > &src)
Dynamic cast to derived class.
Definition: refptr.h:165
void swap(RefPtr< T_CppObject > &lrp, RefPtr< T_CppObject > &rrp)
Swap refptr instances.
Definition: refptr.h:466
int * refcount_ptr() const
For use only in the internal implementation of sharedptr.
Definition: refptr.h:226
Fawkes library namespace.
T_CppObject * operator*() const
Get underlying pointer.
Definition: refptr.h:266
RefPtr< T_CppObject > & operator=(const RefPtr< T_CppObject > &src)
Copy from another RefPtr.
Definition: refptr.h:373
Mutex * refmutex_ptr() const
For use only in the internal implementation of sharedptr.
Definition: refptr.h:245
void reset()
Reset pointer.
Definition: refptr.h:453
void clear()
Set underlying instance to 0, decrementing reference count of existing instance appropriately.
Definition: refptr.h:445
void swap(RefPtr< T_CppObject > &other)
Swap the contents of two RefPtr<>.
Definition: refptr.h:356
static RefPtr< T_CppObject > cast_const(const RefPtr< T_CastFrom > &src)
Cast to non-const.
Definition: refptr.h:205
int use_count() const
Get current reference count.
Definition: refptr.h:235
~RefPtr()
Destructor - decrements reference count.
Definition: refptr.h:277
bool operator!=(const RefPtr< T_CppObject > &src) const
Tests whether the RefPtr<> do not point to the same underlying instance.
Definition: refptr.h:432
RefPtr<> is a reference-counting shared smartpointer.
Definition: refptr.h:49
void swap(LockPtr< T_CppObject > &lrp, LockPtr< T_CppObject > &rrp)
Swap refptr instances.
Definition: lockptr.h:510
T_CppObject * operator->() const
Dereferencing.
Definition: refptr.h:260
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:425
RefPtr()
Default constructor.
Definition: refptr.h:272
static RefPtr< T_CppObject > cast_static(const RefPtr< T_CastFrom > &src)
Static cast to derived class.
Definition: refptr.h:187