Fawkes API  Fawkes Development Version
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.
00043  *
00044  * Note that RefPtr is thread-safe.
00045  *
00046  * @ingroup FCL
00047  */
00048 template <class T_CppObject>
00049 class RefPtr
00050 {
00051  public:
00052   /** Default constructor
00053    *
00054    * Afterwards it will be null and use of -> will cause a segmentation fault.
00055    */
00056   inline RefPtr();
00057   
00058   /// Destructor - decrements reference count.
00059   inline ~RefPtr();
00060 
00061   /** Constructor that takes ownership.
00062    *
00063    * This takes ownership of @a cpp_object, so it will be deleted when the 
00064    * last RefPtr is deleted, for instance when it goes out of scope.
00065    * @param cpp_object C++ object to take ownership of
00066    */
00067   explicit inline RefPtr(T_CppObject* cpp_object);
00068 
00069   /** Copy constructor
00070    * This increments the shared reference count.
00071    * @param src refptr to copy
00072    */
00073   inline RefPtr(const RefPtr<T_CppObject>& src);
00074 
00075   /** Copy constructor (from different, but castable type).
00076    * Increments the reference count.
00077    * @param src refptr to copy
00078    */
00079   template <class T_CastFrom>
00080   inline RefPtr(const RefPtr<T_CastFrom>& src);
00081 
00082   /** Swap the contents of two RefPtr<>.
00083    * This method swaps the internal pointers to T_CppObject.  This can be
00084    * done safely without involving a reference/unreference cycle and is
00085    * therefore highly efficient.
00086    * @param other other instance to swap with.
00087    */
00088   inline void swap(RefPtr<T_CppObject>& other);
00089 
00090   /** Copy from another RefPtr.
00091    * @param src refptr to copy from
00092    * @return reference to this instance
00093    */
00094   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CppObject>& src);
00095 
00096   /** Copy from different, but castable type).
00097    * Increments the reference count.
00098    * @param src refptr to copy from
00099    * @return reference to this instance
00100    */
00101   template <class T_CastFrom>
00102   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CastFrom>& src);
00103 
00104   /** Assign object and claim ownership.
00105    * @param ptr pointer to object, this refptr will claim ownership of the src!
00106    * @return reference to this instance
00107    */
00108   inline RefPtr<T_CppObject>& operator=(T_CppObject *ptr);
00109 
00110 
00111   /** Tests whether the RefPtr<> point to the same underlying instance.
00112    * @param src refptr to compare to
00113    * @return true if both refptrs point to the same instance.
00114    */
00115   inline bool operator==(const RefPtr<T_CppObject>& src) const;
00116   
00117   /** Tests whether the RefPtr<> do not point to the same underlying instance.
00118    * @param src refptr to compare to
00119    * @return true if both refptrs do not point to the same instance.
00120    */
00121   inline bool operator!=(const RefPtr<T_CppObject>& src) const;
00122 
00123   /** Dereferencing.
00124    * Use the methods of the underlying instance like so:
00125    * <code>refptr->memberfun()</code>.
00126    * @return pointer to encapsulated object
00127    */
00128   inline T_CppObject* operator->() const;
00129 
00130   /** Get underlying pointer.
00131    * Use with care!
00132    * @return pointer to encapsulated object
00133    */
00134   inline T_CppObject* operator*() const;
00135 
00136 
00137   /** Test whether the RefPtr<> points to any underlying instance.
00138    *
00139    * Mimics usage of ordinary pointers:
00140    * @code
00141    *   if (ptr)
00142    *     do_something();
00143    * @endcode
00144    */
00145   inline operator bool() const;
00146 
00147   /// Set underlying instance to 0, decrementing reference count of existing instance appropriately.
00148   inline void clear();
00149 
00150   /** Reset pointer.
00151    * Set underlying instance to 0, decrementing reference count of
00152    * existing instance appropriately.
00153    */
00154   inline void reset();
00155 
00156 
00157   /** Dynamic cast to derived class.
00158    *
00159    * The RefPtr can't be cast with the usual notation so instead you can use
00160    * @code
00161    *   ptr_derived = RefPtr<Derived>::cast_dynamic(ptr_base);
00162    * @endcode
00163    * @param src source refptr to cast
00164    * @return refptr to object casted to given type
00165    */
00166   template <class T_CastFrom>
00167   static inline RefPtr<T_CppObject> cast_dynamic(const RefPtr<T_CastFrom>& src);
00168 
00169   /** Static cast to derived class.
00170    *
00171    * Like the dynamic cast; the notation is 
00172    * @code
00173    *   ptr_derived = RefPtr<Derived>::cast_static(ptr_base);
00174    * @endcode
00175    * @param src source refptr to cast
00176    * @return refptr to object casted to given type
00177    */
00178   template <class T_CastFrom>
00179   static inline RefPtr<T_CppObject> cast_static(const RefPtr<T_CastFrom>& src);
00180 
00181   /** Cast to non-const.
00182    *
00183    * The RefPtr can't be cast with the usual notation so instead you can use
00184    * @code
00185    *   ptr_unconst = RefPtr<UnConstType>::cast_const(ptr_const);
00186    * @endcode
00187    * @param src source refptr to cast
00188    * @return refptr to object casted to given type
00189    */
00190   template <class T_CastFrom>
00191   static inline RefPtr<T_CppObject> cast_const(const RefPtr<T_CastFrom>& src);
00192 
00193   /** For use only in the internal implementation of sharedptr.
00194    * @param cpp_object C++ object to wrap
00195    * @param refcount reference count
00196    * @param refmutex reference count mutex
00197    */
00198   explicit inline RefPtr(T_CppObject *cpp_object, int *refcount, Mutex *refmutex);
00199 
00200   /** For use only in the internal implementation of sharedptr.
00201    * Get reference count pointer.
00202    * Warning: This is for internal use only.  Do not manually modify the
00203    * reference count with this pointer.
00204    * @return pointer to refcount integer
00205    */
00206   inline int *  refcount_ptr() const { return __ref_count; }
00207 
00208   /** Get current reference count.
00209    * @return current number of owners referencing this RefPtr.
00210    */
00211   inline int use_count() const { return *__ref_count; }
00212 
00213   /** For use only in the internal implementation of sharedptr.
00214    * Get reference mutex.
00215    * @return pointer to refcount mutex
00216    */
00217   inline Mutex *  refmutex_ptr() const { return __ref_mutex; }
00218 
00219 private:
00220 
00221   T_CppObject   *__cpp_object;
00222   mutable int   *__ref_count;
00223   mutable Mutex *__ref_mutex;
00224 
00225 };
00226 
00227 
00228 // RefPtr<>::operator->() comes first here since it's used by other methods.
00229 // If it would come after them it wouldn't be inlined.
00230 
00231 template <class T_CppObject> inline
00232 T_CppObject* RefPtr<T_CppObject>::operator->() const
00233 {
00234   return __cpp_object;
00235 }
00236 
00237 
00238 template <class T_CppObject> inline
00239 T_CppObject* RefPtr<T_CppObject>::operator*() const
00240 {
00241   return __cpp_object;
00242 }
00243 
00244 template <class T_CppObject> inline
00245 RefPtr<T_CppObject>::RefPtr()
00246 :
00247   __cpp_object(0),
00248   __ref_count(0),
00249   __ref_mutex(0)
00250 {}
00251 
00252 template <class T_CppObject> inline
00253 RefPtr<T_CppObject>::~RefPtr()
00254 {
00255   if(__ref_count && __ref_mutex)
00256   {
00257     __ref_mutex->lock();
00258 
00259     --(*__ref_count);
00260 
00261     if(*__ref_count == 0)
00262     {
00263       if(__cpp_object)
00264       {
00265         delete __cpp_object;
00266         __cpp_object = 0;
00267       }
00268 
00269       delete __ref_count;
00270       delete __ref_mutex;
00271       __ref_count = 0;
00272       __ref_mutex = 0;
00273     } else {
00274       __ref_mutex->unlock();
00275     }
00276   }
00277 }
00278 
00279 
00280 template <class T_CppObject> inline
00281 RefPtr<T_CppObject>::RefPtr(T_CppObject* cpp_object)
00282 :
00283   __cpp_object(cpp_object),
00284   __ref_count(0),
00285   __ref_mutex(0)
00286 {
00287   if(cpp_object)
00288   {
00289     __ref_count = new int;
00290     __ref_mutex = new Mutex();
00291     *__ref_count = 1; //This will be decremented in the destructor.
00292   }
00293 }
00294 
00295 //Used by cast_*() implementations:
00296 template <class T_CppObject> inline
00297   RefPtr<T_CppObject>::RefPtr(T_CppObject* cpp_object, int* refcount, Mutex *refmutex)
00298 :
00299   __cpp_object(cpp_object),
00300   __ref_count(refcount),
00301   __ref_mutex(refmutex)
00302 {
00303   if(__cpp_object && __ref_count && __ref_mutex) {
00304     __ref_mutex->lock();
00305     ++(*__ref_count);
00306     __ref_mutex->unlock();
00307   }
00308 }
00309 
00310 template <class T_CppObject> inline
00311 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CppObject>& src)
00312 :
00313   __cpp_object (src.__cpp_object),
00314   __ref_count(src.__ref_count),
00315   __ref_mutex(src.__ref_mutex)
00316 {
00317   if(__cpp_object && __ref_count && __ref_mutex)
00318   {
00319     __ref_mutex->lock();
00320     ++(*__ref_count);
00321     __ref_mutex->unlock();
00322   }
00323 }
00324 
00325 // The templated ctor allows copy construction from any object that's
00326 // castable.  Thus, it does downcasts:
00327 //   base_ref = derived_ref
00328 template <class T_CppObject>
00329   template <class T_CastFrom>
00330 inline
00331 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CastFrom>& src)
00332 :
00333   // A different RefPtr<> will not allow us access to __cpp_object.  We need
00334   // to add a get_underlying() for this, but that would encourage incorrect
00335   // use, so we use the less well-known operator->() accessor:
00336   __cpp_object (src.operator->()),
00337   __ref_count(src.refcount_ptr()),
00338   __ref_mutex(src.refmutex_ptr())
00339 {
00340   if(__cpp_object && __ref_count && __ref_mutex) {
00341     __ref_mutex->lock();
00342     ++(*__ref_count);
00343     __ref_mutex->unlock();
00344   }
00345 }
00346 
00347 template <class T_CppObject> inline
00348 void
00349 RefPtr<T_CppObject>::swap(RefPtr<T_CppObject>& other)
00350 {
00351   T_CppObject *const temp = __cpp_object;
00352   int *temp_count         = __ref_count; 
00353   Mutex *temp_mutex       = __ref_mutex;
00354 
00355   __cpp_object = other.__cpp_object;
00356   __ref_count  = other.__ref_count;
00357   __ref_mutex  = other.__ref_mutex;
00358 
00359   other.__cpp_object = temp;
00360   other.__ref_count  = temp_count;
00361   other.__ref_mutex  = temp_mutex;
00362 }
00363 
00364 template <class T_CppObject> inline
00365 RefPtr<T_CppObject>&
00366 RefPtr<T_CppObject>::operator=(const RefPtr<T_CppObject>& src)
00367 {
00368   // In case you haven't seen the swap() technique to implement copy
00369   // assignment before, here's what it does:
00370   //
00371   // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
00372   //    increasing the reference count of the source object.
00373   //
00374   // 2) Swap the internal object pointers of *this and the temporary
00375   //    RefPtr<>.  After this step, *this already contains the new pointer,
00376   //    and the old pointer is now managed by temp.
00377   //
00378   // 3) The destructor of temp is executed, thereby unreferencing the
00379   //    old object pointer.
00380   //
00381   // This technique is described in Herb Sutter's "Exceptional C++", and
00382   // has a number of advantages over conventional approaches:
00383   //
00384   // - Code reuse by calling the copy ctor.
00385   // - Strong exception safety for free.
00386   // - Self assignment is handled implicitely.
00387   // - Simplicity.
00388   // - It just works and is hard to get wrong; i.e. you can use it without
00389   //   even thinking about it to implement copy assignment whereever the
00390   //   object data is managed indirectly via a pointer, which is very common.
00391 
00392   RefPtr<T_CppObject> temp (src);
00393   this->swap(temp);
00394   return *this;
00395 }
00396 
00397 template <class T_CppObject> inline
00398 RefPtr<T_CppObject>&
00399 RefPtr<T_CppObject>::operator=(T_CppObject *ptr)
00400 {
00401   RefPtr<T_CppObject> temp(ptr);
00402   this->swap(temp);
00403   return *this;
00404 }
00405 
00406 
00407 template <class T_CppObject>
00408   template <class T_CastFrom>
00409 inline
00410 RefPtr<T_CppObject>&
00411 RefPtr<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src)
00412 {
00413   RefPtr<T_CppObject> temp (src);
00414   this->swap(temp);
00415   return *this;
00416 }
00417 
00418 template <class T_CppObject> inline
00419 bool
00420 RefPtr<T_CppObject>::operator==(const RefPtr<T_CppObject>& src) const
00421 {
00422   return (__cpp_object == src.__cpp_object);
00423 }
00424 
00425 template <class T_CppObject> inline
00426 bool
00427 RefPtr<T_CppObject>::operator!=(const RefPtr<T_CppObject>& src) const
00428 {
00429   return (__cpp_object != src.__cpp_object);
00430 }
00431 
00432 template <class T_CppObject> inline
00433 RefPtr<T_CppObject>::operator bool() const
00434 {
00435   return (__cpp_object != 0);
00436 }
00437 
00438 template <class T_CppObject> inline
00439 void RefPtr<T_CppObject>::clear()
00440 {
00441   RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
00442   this->swap(temp);
00443 }
00444 
00445 template <class T_CppObject> inline
00446 void RefPtr<T_CppObject>::reset()
00447 {
00448   RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
00449   this->swap(temp);
00450 }
00451 
00452 template <class T_CppObject>
00453   template <class T_CastFrom>
00454 inline
00455 RefPtr<T_CppObject>
00456 RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src)
00457 {
00458   T_CppObject *const cpp_object = dynamic_cast<T_CppObject*>(src.operator->());
00459 
00460   if(cpp_object) //Check whether dynamic_cast<> succeeded so we don't pass a null object with a used refcount:
00461     return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
00462   else
00463     return RefPtr<T_CppObject>();
00464 }
00465 
00466 template <class T_CppObject>
00467   template <class T_CastFrom>
00468 inline
00469 RefPtr<T_CppObject>
00470 RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src)
00471 {
00472   T_CppObject *const cpp_object = static_cast<T_CppObject*>(src.operator->());
00473 
00474   return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
00475 }
00476 
00477 template <class T_CppObject>
00478   template <class T_CastFrom>
00479 inline
00480 RefPtr<T_CppObject>
00481 RefPtr<T_CppObject>::cast_const(const RefPtr<T_CastFrom>& src)
00482 {
00483   T_CppObject *const cpp_object = const_cast<T_CppObject*>(src.operator->());
00484 
00485   return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
00486 }
00487 
00488 
00489 /** Swap refptr instances.
00490  * @param lrp "left" refptr
00491  * @param rrp "right" refptr
00492  * @relates fawkes::RefPtr
00493  */
00494 template <class T_CppObject> inline
00495 void
00496 swap(RefPtr<T_CppObject>& lrp, RefPtr<T_CppObject>& rrp)
00497 {
00498   lrp.swap(rrp);
00499 }
00500 
00501 } // end namespace fawkes
00502 
00503 
00504 #endif