refptr.h

00001
00002 /***************************************************************************
00003  *  refptr.h - reference counting shared smartpointer
00004  *
00005  *  Created: Sat Jan 24 12:29:41 2009
00006  *  Copyright  2002  The gtkmm Development Team
00007  *             2005  The cairomm Development Team
00008  *             2009  Tim Niemueller [www.niemueller.de]
00009  *
00010  ****************************************************************************/
00011
00012 /*  This program is free software; you can redistribute it and/or modify
00013  *  it under the terms of the GNU General Public License as published by
00014  *  the Free Software Foundation; either version 2 of the License, or
00015  *  (at your option) any later version. A runtime exception applies to
00016  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00017  *
00018  *  This program is distributed in the hope that it will be useful,
00019  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  *  GNU Library General Public License for more details.
00022  *
00023  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00024  */
00025
00026 #ifndef __CORE_UTILS_REFPTR_H_
00027 #define __CORE_UTILS_REFPTR_H_
00028 
00029 #include <core/threading/mutex.h>
00030
00031 namespace fawkes {
00032 
00033 /** RefPtr<> is a reference-counting shared smartpointer.
00034  *
00035  * Reference counting means that a shared reference count is incremented each
00036  * time a RefPtr is copied, and decremented each time a RefPtr is destroyed,
00037  * for instance when it leaves its scope. When the reference count reaches
00038  * zero, the contained object is deleted
00039  *
00040  * Fawkes uses RefPtr so that you don't need to remember
00041  * to delete the object explicitly, or know when a method expects you to delete 
00042  * the object that it returns, and to prevent any need to manually reference 
00043  * and unreference cairo objects.
00044  *
00045  * Note that RefPtr is thread-safe.
00046  *
00047  * @ingroup FCL
00048  */
00049 template <class T_CppObject>
00050 class RefPtr
00051 {
00052  public:
00053   /** Default constructor
00054    *
00055    * Afterwards it will be null and use of -> will cause a segmentation fault.
00056    */
00057   inline RefPtr();
00058   
00059   /// Destructor - decrements reference count.
00060   inline ~RefPtr();
00061 
00062   /** Constructor that takes ownership.
00063    *
00064    * This takes ownership of @a cpp_object, so it will be deleted when the 
00065    * last RefPtr is deleted, for instance when it goes out of scope.
00066    * @param cpp_object C++ object to take ownership of
00067    */
00068   explicit inline RefPtr(T_CppObject* cpp_object);
00069 
00070   /** Copy constructor
00071    * This increments the shared reference count.
00072    * @param src refptr to copy
00073    */
00074   inline RefPtr(const RefPtr<T_CppObject>& src);
00075 
00076   /** Copy constructor (from different, but castable type).
00077    * Increments the reference count.
00078    * @param src refptr to copy
00079    */
00080   template <class T_CastFrom>
00081   inline RefPtr(const RefPtr<T_CastFrom>& src);
00082 
00083   /** Swap the contents of two RefPtr<>.
00084    * This method swaps the internal pointers to T_CppObject.  This can be
00085    * done safely without involving a reference/unreference cycle and is
00086    * therefore highly efficient.
00087    * @param other other instance to swap with.
00088    */
00089   inline void swap(RefPtr<T_CppObject>& other);
00090 
00091   /** Copy from another RefPtr.
00092    * @param src refptr to copy from
00093    * @return reference to this instance
00094    */
00095   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CppObject>& src);
00096 
00097   /** Copy from different, but castable type).
00098    * Increments the reference count.
00099    * @param src refptr to copy from
00100    * @return reference to this instance
00101    */
00102   template <class T_CastFrom>
00103   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CastFrom>& src);
00104 
00105   /** Assign object and claim ownership.
00106    * @param ptr pointer to object, this refptr will claim ownership of the src!
00107    * @return reference to this instance
00108    */
00109   inline RefPtr<T_CppObject>& operator=(T_CppObject *ptr);
00110
00111 
00112   /** Tests whether the RefPtr<> point to the same underlying instance.
00113    * @param src refptr to compare to
00114    * @return true if both refptrs point to the same instance.
00115    */
00116   inline bool operator==(const RefPtr<T_CppObject>& src) const;
00117   
00118   /** Tests whether the RefPtr<> do not point to the same underlying instance.
00119    * @param src refptr to compare to
00120    * @return true if both refptrs do not point to the same instance.
00121    */
00122   inline bool operator!=(const RefPtr<T_CppObject>& src) const;
00123 
00124   /** Dereferencing.
00125    * Use the methods of the underlying instance like so:
00126    * <code>refptr->memberfun()</code>.
00127    */
00128   inline T_CppObject* operator->() const;
00129 
00130   /** Test whether the RefPtr<> points to any underlying instance.
00131    *
00132    * Mimics usage of ordinary pointers:
00133    * @code
00134    *   if (ptr)
00135    *     do_something();
00136    * @endcode
00137    */
00138   inline operator bool() const;
00139 
00140   /// Set underlying instance to 0, decrementing reference count of existing instance appropriately.
00141   inline void clear();
00142
00143 
00144   /** Dynamic cast to derived class.
00145    *
00146    * The RefPtr can't be cast with the usual notation so instead you can use
00147    * @code
00148    *   ptr_derived = RefPtr<Derived>::cast_dynamic(ptr_base);
00149    * @endcode
00150    * @param src source refptr to cast
00151    * @return refptr to object casted to given type
00152    */
00153   template <class T_CastFrom>
00154   static inline RefPtr<T_CppObject> cast_dynamic(const RefPtr<T_CastFrom>& src);
00155 
00156   /** Static cast to derived class.
00157    *
00158    * Like the dynamic cast; the notation is 
00159    * @code
00160    *   ptr_derived = RefPtr<Derived>::cast_static(ptr_base);
00161    * @endcode
00162    * @param src source refptr to cast
00163    * @return refptr to object casted to given type
00164    */
00165   template <class T_CastFrom>
00166   static inline RefPtr<T_CppObject> cast_static(const RefPtr<T_CastFrom>& src);
00167 
00168   /** Cast to non-const.
00169    *
00170    * The RefPtr can't be cast with the usual notation so instead you can use
00171    * @code
00172    *   ptr_unconst = RefPtr<UnConstType>::cast_const(ptr_const);
00173    * @endcode
00174    * @param src source refptr to cast
00175    * @return refptr to object casted to given type
00176    */
00177   template <class T_CastFrom>
00178   static inline RefPtr<T_CppObject> cast_const(const RefPtr<T_CastFrom>& src);
00179 
00180   /** For use only in the internal implementation of sharedptr.
00181    * @param cpp_object C++ object to wrap
00182    * @param refcount reference count
00183    * @param refmutex reference count mutex
00184    */
00185   explicit inline RefPtr(T_CppObject *cpp_object, int *refcount, Mutex *refmutex);
00186 
00187   /** For use only in the internal implementation of sharedptr.
00188    * Get reference count pointer.
00189    * Warning: This is for internal use only.  Do not manually modify the
00190    * reference count with this pointer.
00191    * @return pointer to refcount integer
00192    */
00193   inline int *  refcount_ptr() const { return __ref_count; }
00194 
00195   /** For use only in the internal implementation of sharedptr.
00196    * Get reference mutex.
00197    * @return pointer to refcount mutex
00198    */
00199   inline Mutex *  refmutex_ptr() const { return __ref_mutex; }
00200
00201 private:
00202
00203   T_CppObject   *__cpp_object;
00204   mutable int   *__ref_count;
00205   mutable Mutex *__ref_mutex;
00206
00207 };
00208
00209
00210 // RefPtr<>::operator->() comes first here since it's used by other methods.
00211 // If it would come after them it wouldn't be inlined.
00212
00213 template <class T_CppObject> inline
00214 T_CppObject* RefPtr<T_CppObject>::operator->() const
00215 {
00216   return __cpp_object;
00217 }
00218
00219 template <class T_CppObject> inline
00220 RefPtr<T_CppObject>::RefPtr()
00221 :
00222   __cpp_object(0),
00223   __ref_count(0),
00224   __ref_mutex(0)
00225 {}
00226
00227 template <class T_CppObject> inline
00228 RefPtr<T_CppObject>::~RefPtr()
00229 {
00230   if(__ref_count && __ref_mutex)
00231   {
00232     __ref_mutex->lock();
00233
00234     --(*__ref_count);
00235
00236     if(*__ref_count == 0)
00237     {
00238       if(__cpp_object)
00239       {
00240         delete __cpp_object;
00241         __cpp_object = 0;
00242       }
00243
00244       delete __ref_count;
00245       delete __ref_mutex;
00246       __ref_count = 0;
00247       __ref_mutex = 0;
00248     } else {
00249       __ref_mutex->unlock();
00250     }
00251   }
00252 }
00253
00254
00255 template <class T_CppObject> inline
00256 RefPtr<T_CppObject>::RefPtr(T_CppObject* cpp_object)
00257 :
00258   __cpp_object(cpp_object),
00259   __ref_count(0),
00260   __ref_mutex(0)
00261 {
00262   if(cpp_object)
00263   {
00264     __ref_count = new int;
00265     __ref_mutex = new Mutex();
00266     *__ref_count = 1; //This will be decremented in the destructor.
00267   }
00268 }
00269
00270 //Used by cast_*() implementations:
00271 template <class T_CppObject> inline
00272   RefPtr<T_CppObject>::RefPtr(T_CppObject* cpp_object, int* refcount, Mutex *refmutex)
00273 :
00274   __cpp_object(cpp_object),
00275   __ref_count(refcount),
00276   __ref_mutex(refmutex)
00277 {
00278   if(__cpp_object && __ref_count && __ref_mutex) {
00279     __ref_mutex->lock();
00280     ++(*__ref_count);
00281     __ref_mutex->unlock();
00282   }
00283 }
00284
00285 template <class T_CppObject> inline
00286 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CppObject>& src)
00287 :
00288   __cpp_object (src.__cpp_object),
00289   __ref_count(src.__ref_count),
00290   __ref_mutex(src.__ref_mutex)
00291 {
00292   if(__cpp_object && __ref_count && __ref_mutex)
00293   {
00294     __ref_mutex->lock();
00295     ++(*__ref_count);
00296     __ref_mutex->unlock();
00297   }
00298 }
00299
00300 // The templated ctor allows copy construction from any object that's
00301 // castable.  Thus, it does downcasts:
00302 //   base_ref = derived_ref
00303 template <class T_CppObject>
00304   template <class T_CastFrom>
00305 inline
00306 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CastFrom>& src)
00307 :
00308   // A different RefPtr<> will not allow us access to __cpp_object.  We need
00309   // to add a get_underlying() for this, but that would encourage incorrect
00310   // use, so we use the less well-known operator->() accessor:
00311   __cpp_object (src.operator->()),
00312   __ref_count(src.refcount_ptr()),
00313   __ref_mutex(src.refmutex_ptr())
00314 {
00315   if(__cpp_object && __ref_count && __ref_mutex) {
00316     __ref_mutex->lock();
00317     ++(*__ref_count);
00318     __ref_mutex->unlock();
00319   }
00320 }
00321
00322 template <class T_CppObject> inline
00323 void
00324 RefPtr<T_CppObject>::swap(RefPtr<T_CppObject>& other)
00325 {
00326   T_CppObject *const temp = __cpp_object;
00327   int *temp_count         = __ref_count;
00328   Mutex *temp_mutex       = __ref_mutex;
00329
00330   __cpp_object = other.__cpp_object;
00331   __ref_count  = other.__ref_count;
00332   __ref_mutex  = other.__ref_mutex;
00333
00334   other.__cpp_object = temp;
00335   other.__ref_count  = temp_count;
00336   other.__ref_mutex  = temp_mutex;
00337 }
00338
00339 template <class T_CppObject> inline
00340 RefPtr<T_CppObject>&
00341 RefPtr<T_CppObject>::operator=(const RefPtr<T_CppObject>& src)
00342 {
00343   // In case you haven't seen the swap() technique to implement copy
00344   // assignment before, here's what it does:
00345   //
00346   // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
00347   //    increasing the reference count of the source object.
00348   //
00349   // 2) Swap the internal object pointers of *this and the temporary
00350   //    RefPtr<>.  After this step, *this already contains the new pointer,
00351   //    and the old pointer is now managed by temp.
00352   //
00353   // 3) The destructor of temp is executed, thereby unreferencing the
00354   //    old object pointer.
00355   //
00356   // This technique is described in Herb Sutter's "Exceptional C++", and
00357   // has a number of advantages over conventional approaches:
00358   //
00359   // - Code reuse by calling the copy ctor.
00360   // - Strong exception safety for free.
00361   // - Self assignment is handled implicitely.
00362   // - Simplicity.
00363   // - It just works and is hard to get wrong; i.e. you can use it without
00364   //   even thinking about it to implement copy assignment whereever the
00365   //   object data is managed indirectly via a pointer, which is very common.
00366
00367   RefPtr<T_CppObject> temp (src);
00368   this->swap(temp);
00369   return *this;
00370 }
00371
00372 template <class T_CppObject> inline
00373 RefPtr<T_CppObject>&
00374 RefPtr<T_CppObject>::operator=(T_CppObject *ptr)
00375 {
00376   RefPtr<T_CppObject> temp(ptr);
00377   this->swap(temp);
00378   return *this;
00379 }
00380
00381
00382 template <class T_CppObject>
00383   template <class T_CastFrom>
00384 inline
00385 RefPtr<T_CppObject>&
00386 RefPtr<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src)
00387 {
00388   RefPtr<T_CppObject> temp (src);
00389   this->swap(temp);
00390   return *this;
00391 }
00392
00393 template <class T_CppObject> inline
00394 bool
00395 RefPtr<T_CppObject>::operator==(const RefPtr<T_CppObject>& src) const
00396 {
00397   return (__cpp_object == src.__cpp_object);
00398 }
00399
00400 template <class T_CppObject> inline
00401 bool
00402 RefPtr<T_CppObject>::operator!=(const RefPtr<T_CppObject>& src) const
00403 {
00404   return (__cpp_object != src.__cpp_object);
00405 }
00406
00407 template <class T_CppObject> inline
00408 RefPtr<T_CppObject>::operator bool() const
00409 {
00410   return (__cpp_object != 0);
00411 }
00412
00413 template <class T_CppObject> inline
00414 void RefPtr<T_CppObject>::clear()
00415 {
00416   RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
00417   this->swap(temp);
00418 }
00419
00420 template <class T_CppObject>
00421   template <class T_CastFrom>
00422 inline
00423 RefPtr<T_CppObject>
00424 RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src)
00425 {
00426   T_CppObject *const cpp_object = dynamic_cast<T_CppObject*>(src.operator->());
00427
00428   if(cpp_object) //Check whether dynamic_cast<> succeeded so we don't pass a null object with a used refcount:
00429     return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
00430   else
00431     return RefPtr<T_CppObject>();
00432 }
00433
00434 template <class T_CppObject>
00435   template <class T_CastFrom>
00436 inline
00437 RefPtr<T_CppObject>
00438 RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src)
00439 {
00440   T_CppObject *const cpp_object = static_cast<T_CppObject*>(src.operator->());
00441
00442   return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
00443 }
00444
00445 template <class T_CppObject>
00446   template <class T_CastFrom>
00447 inline
00448 RefPtr<T_CppObject>
00449 RefPtr<T_CppObject>::cast_const(const RefPtr<T_CastFrom>& src)
00450 {
00451   T_CppObject *const cpp_object = const_cast<T_CppObject*>(src.operator->());
00452
00453   return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
00454 }
00455
00456 
00457 /** Swap refptr instances.
00458  * @param lrp "left" refptr
00459  * @param rrp "right" refptr
00460  * @relates fawkes::RefPtr
00461  */
00462 template <class T_CppObject> inline
00463 void
00464 swap(RefPtr<T_CppObject>& lrp, RefPtr<T_CppObject>& rrp)
00465 {
00466   lrp.swap(rrp);
00467 }
00468
00469 } // end namespace fawkes
00470
00471
00472 #endif