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 *
262 {
263  return cpp_object_;
264 }
265 
266 template <class T_CppObject>
267 inline T_CppObject *
269 {
270  return cpp_object_;
271 }
272 
273 template <class T_CppObject>
274 inline RefPtr<T_CppObject>::RefPtr() : cpp_object_(0), ref_count_(0), ref_mutex_(0)
275 {
276 }
277 
278 template <class T_CppObject>
280 {
281  if (ref_count_ && ref_mutex_) {
282  ref_mutex_->lock();
283 
284  --(*ref_count_);
285 
286  if (*ref_count_ == 0) {
287  if (cpp_object_) {
288  delete cpp_object_;
289  cpp_object_ = 0;
290  }
291 
292  delete ref_count_;
293  delete ref_mutex_;
294  ref_count_ = 0;
295  ref_mutex_ = 0;
296  } else {
297  ref_mutex_->unlock();
298  }
299  }
300 }
301 
302 template <class T_CppObject>
303 inline RefPtr<T_CppObject>::RefPtr(T_CppObject *cpp_object)
304 : cpp_object_(cpp_object), ref_count_(0), ref_mutex_(0)
305 {
306  if (cpp_object) {
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>
315 inline RefPtr<T_CppObject>::RefPtr(T_CppObject *cpp_object, int *refcount, Mutex *refmutex)
316 : cpp_object_(cpp_object), ref_count_(refcount), ref_mutex_(refmutex)
317 {
318  if (cpp_object_ && ref_count_ && ref_mutex_) {
319  ref_mutex_->lock();
320  ++(*ref_count_);
321  ref_mutex_->unlock();
322  }
323 }
324 
325 template <class T_CppObject>
327 : cpp_object_(src.cpp_object_), ref_count_(src.ref_count_), ref_mutex_(src.ref_mutex_)
328 {
329  if (cpp_object_ && ref_count_ && ref_mutex_) {
330  ref_mutex_->lock();
331  ++(*ref_count_);
332  ref_mutex_->unlock();
333  }
334 }
335 
336 // The templated ctor allows copy construction from any object that's
337 // castable. Thus, it does downcasts:
338 // base_ref = derived_ref
339 template <class T_CppObject>
340 template <class T_CastFrom>
342 : // A different RefPtr<> will not allow us access to cpp_object_. We need
343  // to add a get_underlying() for this, but that would encourage incorrect
344  // use, so we use the less well-known operator->() accessor:
345  cpp_object_(src.operator->()),
346  ref_count_(src.refcount_ptr()),
347  ref_mutex_(src.refmutex_ptr())
348 {
349  if (cpp_object_ && ref_count_ && ref_mutex_) {
350  ref_mutex_->lock();
351  ++(*ref_count_);
352  ref_mutex_->unlock();
353  }
354 }
355 
356 template <class T_CppObject>
357 inline void
359 {
360  T_CppObject *const temp = cpp_object_;
361  int * temp_count = ref_count_;
362  Mutex * temp_mutex = ref_mutex_;
363 
364  cpp_object_ = other.cpp_object_;
365  ref_count_ = other.ref_count_;
366  ref_mutex_ = other.ref_mutex_;
367 
368  other.cpp_object_ = temp;
369  other.ref_count_ = temp_count;
370  other.ref_mutex_ = temp_mutex;
371 }
372 
373 template <class T_CppObject>
374 inline RefPtr<T_CppObject> &
376 {
377  // In case you haven't seen the swap() technique to implement copy
378  // assignment before, here's what it does:
379  //
380  // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
381  // increasing the reference count of the source object.
382  //
383  // 2) Swap the internal object pointers of *this and the temporary
384  // RefPtr<>. After this step, *this already contains the new pointer,
385  // and the old pointer is now managed by temp.
386  //
387  // 3) The destructor of temp is executed, thereby unreferencing the
388  // old object pointer.
389  //
390  // This technique is described in Herb Sutter's "Exceptional C++", and
391  // has a number of advantages over conventional approaches:
392  //
393  // - Code reuse by calling the copy ctor.
394  // - Strong exception safety for free.
395  // - Self assignment is handled implicitely.
396  // - Simplicity.
397  // - It just works and is hard to get wrong; i.e. you can use it without
398  // even thinking about it to implement copy assignment whereever the
399  // object data is managed indirectly via a pointer, which is very common.
400 
401  RefPtr<T_CppObject> temp(src);
402  this->swap(temp);
403  return *this;
404 }
405 
406 template <class T_CppObject>
407 inline RefPtr<T_CppObject> &
409 {
410  RefPtr<T_CppObject> temp(ptr);
411  this->swap(temp);
412  return *this;
413 }
414 
415 template <class T_CppObject>
416 template <class T_CastFrom>
417 inline RefPtr<T_CppObject> &
419 {
420  RefPtr<T_CppObject> temp(src);
421  this->swap(temp);
422  return *this;
423 }
424 
425 template <class T_CppObject>
426 inline bool
428 {
429  return (cpp_object_ == src.cpp_object_);
430 }
431 
432 template <class T_CppObject>
433 inline bool
435 {
436  return (cpp_object_ != src.cpp_object_);
437 }
438 
439 template <class T_CppObject>
440 inline RefPtr<T_CppObject>::operator bool() const
441 {
442  return (cpp_object_ != 0);
443 }
444 
445 template <class T_CppObject>
446 inline void
448 {
449  RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
450  this->swap(temp);
451 }
452 
453 template <class T_CppObject>
454 inline void
456 {
457  RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
458  this->swap(temp);
459 }
460 
461 /** Swap refptr instances.
462  * @param lrp "left" refptr
463  * @param rrp "right" refptr
464  * @relates fawkes::RefPtr
465  */
466 template <class T_CppObject>
467 inline void
469 {
470  lrp.swap(rrp);
471 }
472 
473 } // end namespace fawkes
474 
475 #endif
fawkes::Mutex::lock
void lock()
Lock this mutex.
Definition: mutex.cpp:87
fawkes::RefPtr::~RefPtr
~RefPtr()
Destructor - decrements reference count.
Definition: refptr.h:279
fawkes::RefPtr::use_count
int use_count() const
Get current reference count.
Definition: refptr.h:235
fawkes::Mutex
Mutex mutual exclusion lock.
Definition: mutex.h:33
fawkes::RefPtr
RefPtr<> is a reference-counting shared smartpointer.
Definition: refptr.h:50
fawkes::RefPtr::operator=
RefPtr< T_CppObject > & operator=(const RefPtr< T_CastFrom > &src)
Copy from different, but castable type).
Definition: refptr.h:418
fawkes::RefPtr::operator!=
bool operator!=(const RefPtr< T_CppObject > &src) const
Tests whether the RefPtr<> do not point to the same underlying instance.
Definition: refptr.h:434
fawkes::RefPtr::cast_static
static RefPtr< T_CppObject > cast_static(const RefPtr< T_CastFrom > &src)
Static cast to derived class.
Definition: refptr.h:187
fawkes::Mutex::unlock
void unlock()
Unlock the mutex.
Definition: mutex.cpp:131
fawkes::RefPtr::operator==
bool operator==(const RefPtr< T_CppObject > &src) const
Tests whether the RefPtr<> point to the same underlying instance.
Definition: refptr.h:427
fawkes::RefPtr::operator->
T_CppObject * operator->() const
Dereferencing.
Definition: refptr.h:261
fawkes::RefPtr::RefPtr
RefPtr(T_CppObject *cpp_object, int *refcount, Mutex *refmutex)
For use only in the internal implementation of sharedptr.
Definition: refptr.h:315
fawkes::RefPtr::cast_dynamic
static RefPtr< T_CppObject > cast_dynamic(const RefPtr< T_CastFrom > &src)
Dynamic cast to derived class.
Definition: refptr.h:165
fawkes::RefPtr::RefPtr
RefPtr(const RefPtr< T_CastFrom > &src)
Copy constructor (from different, but castable type).
Definition: refptr.h:341
fawkes
Fawkes library namespace.
fawkes::RefPtr::RefPtr
RefPtr()
Default constructor.
Definition: refptr.h:274
fawkes::RefPtr::RefPtr
RefPtr(T_CppObject *cpp_object)
Constructor that takes ownership.
Definition: refptr.h:303
fawkes::RefPtr::swap
void swap(RefPtr< T_CppObject > &lrp, RefPtr< T_CppObject > &rrp)
Swap refptr instances.
Definition: refptr.h:468
fawkes::RefPtr::operator*
T_CppObject * operator*() const
Get underlying pointer.
Definition: refptr.h:268
fawkes::RefPtr::refcount_ptr
int * refcount_ptr() const
For use only in the internal implementation of sharedptr.
Definition: refptr.h:226
fawkes::RefPtr::operator=
RefPtr< T_CppObject > & operator=(T_CppObject *ptr)
Assign object and claim ownership.
Definition: refptr.h:408
fawkes::RefPtr::clear
void clear()
Set underlying instance to 0, decrementing reference count of existing instance appropriately.
Definition: refptr.h:447
fawkes::RefPtr::swap
void swap(RefPtr< T_CppObject > &other)
Swap the contents of two RefPtr<>.
Definition: refptr.h:358
fawkes::RefPtr::RefPtr
RefPtr(const RefPtr< T_CppObject > &src)
Copy constructor This increments the shared reference count.
Definition: refptr.h:326
fawkes::RefPtr::reset
void reset()
Reset pointer.
Definition: refptr.h:455
fawkes::RefPtr::operator=
RefPtr< T_CppObject > & operator=(const RefPtr< T_CppObject > &src)
Copy from another RefPtr.
Definition: refptr.h:375
fawkes::RefPtr::refmutex_ptr
Mutex * refmutex_ptr() const
For use only in the internal implementation of sharedptr.
Definition: refptr.h:245
fawkes::RefPtr::cast_const
static RefPtr< T_CppObject > cast_const(const RefPtr< T_CastFrom > &src)
Cast to non-const.
Definition: refptr.h:205