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    * @return pointer to encapsulated object
00128    */
00129   inline T_CppObject* operator->() const;
00130 
00131   /** Test whether the RefPtr<> points to any underlying instance.
00132    *
00133    * Mimics usage of ordinary pointers:
00134    * @code
00135    *   if (ptr)
00136    *     do_something();
00137    * @endcode
00138    */
00139   inline operator bool() const;
00140 
00141   /// Set underlying instance to 0, decrementing reference count of existing instance appropriately.
00142   inline void clear();
00143 
00144 
00145   /** Dynamic cast to derived class.
00146    *
00147    * The RefPtr can't be cast with the usual notation so instead you can use
00148    * @code
00149    *   ptr_derived = RefPtr<Derived>::cast_dynamic(ptr_base);
00150    * @endcode
00151    * @param src source refptr to cast
00152    * @return refptr to object casted to given type
00153    */
00154   template <class T_CastFrom>
00155   static inline RefPtr<T_CppObject> cast_dynamic(const RefPtr<T_CastFrom>& src);
00156 
00157   /** Static cast to derived class.
00158    *
00159    * Like the dynamic cast; the notation is 
00160    * @code
00161    *   ptr_derived = RefPtr<Derived>::cast_static(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_static(const RefPtr<T_CastFrom>& src);
00168 
00169   /** Cast to non-const.
00170    *
00171    * The RefPtr can't be cast with the usual notation so instead you can use
00172    * @code
00173    *   ptr_unconst = RefPtr<UnConstType>::cast_const(ptr_const);
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_const(const RefPtr<T_CastFrom>& src);
00180 
00181   /** For use only in the internal implementation of sharedptr.
00182    * @param cpp_object C++ object to wrap
00183    * @param refcount reference count
00184    * @param refmutex reference count mutex
00185    */
00186   explicit inline RefPtr(T_CppObject *cpp_object, int *refcount, Mutex *refmutex);
00187 
00188   /** For use only in the internal implementation of sharedptr.
00189    * Get reference count pointer.
00190    * Warning: This is for internal use only.  Do not manually modify the
00191    * reference count with this pointer.
00192    * @return pointer to refcount integer
00193    */
00194   inline int *  refcount_ptr() const { return __ref_count; }
00195 
00196   /** For use only in the internal implementation of sharedptr.
00197    * Get reference mutex.
00198    * @return pointer to refcount mutex
00199    */
00200   inline Mutex *  refmutex_ptr() const { return __ref_mutex; }
00201 
00202 private:
00203 
00204   T_CppObject   *__cpp_object;
00205   mutable int   *__ref_count;
00206   mutable Mutex *__ref_mutex;
00207 
00208 };
00209 
00210 
00211 // RefPtr<>::operator->() comes first here since it's used by other methods.
00212 // If it would come after them it wouldn't be inlined.
00213 
00214 template <class T_CppObject> inline
00215 T_CppObject* RefPtr<T_CppObject>::operator->() const
00216 {
00217   return __cpp_object;
00218 }
00219 
00220 template <class T_CppObject> inline
00221 RefPtr<T_CppObject>::RefPtr()
00222 :
00223   __cpp_object(0),
00224   __ref_count(0),
00225   __ref_mutex(0)
00226 {}
00227 
00228 template <class T_CppObject> inline
00229 RefPtr<T_CppObject>::~RefPtr()
00230 {
00231   if(__ref_count && __ref_mutex)
00232   {
00233     __ref_mutex->lock();
00234 
00235     --(*__ref_count);
00236 
00237     if(*__ref_count == 0)
00238     {
00239       if(__cpp_object)
00240       {
00241         delete __cpp_object;
00242         __cpp_object = 0;
00243       }
00244 
00245       delete __ref_count;
00246       delete __ref_mutex;
00247       __ref_count = 0;
00248       __ref_mutex = 0;
00249     } else {
00250       __ref_mutex->unlock();
00251     }
00252   }
00253 }
00254 
00255 
00256 template <class T_CppObject> inline
00257 RefPtr<T_CppObject>::RefPtr(T_CppObject* cpp_object)
00258 :
00259   __cpp_object(cpp_object),
00260   __ref_count(0),
00261   __ref_mutex(0)
00262 {
00263   if(cpp_object)
00264   {
00265     __ref_count = new int;
00266     __ref_mutex = new Mutex();
00267     *__ref_count = 1; //This will be decremented in the destructor.
00268   }
00269 }
00270 
00271 //Used by cast_*() implementations:
00272 template <class T_CppObject> inline
00273   RefPtr<T_CppObject>::RefPtr(T_CppObject* cpp_object, int* refcount, Mutex *refmutex)
00274 :
00275   __cpp_object(cpp_object),
00276   __ref_count(refcount),
00277   __ref_mutex(refmutex)
00278 {
00279   if(__cpp_object && __ref_count && __ref_mutex) {
00280     __ref_mutex->lock();
00281     ++(*__ref_count);
00282     __ref_mutex->unlock();
00283   }
00284 }
00285 
00286 template <class T_CppObject> inline
00287 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CppObject>& src)
00288 :
00289   __cpp_object (src.__cpp_object),
00290   __ref_count(src.__ref_count),
00291   __ref_mutex(src.__ref_mutex)
00292 {
00293   if(__cpp_object && __ref_count && __ref_mutex)
00294   {
00295     __ref_mutex->lock();
00296     ++(*__ref_count);
00297     __ref_mutex->unlock();
00298   }
00299 }
00300 
00301 // The templated ctor allows copy construction from any object that's
00302 // castable.  Thus, it does downcasts:
00303 //   base_ref = derived_ref
00304 template <class T_CppObject>
00305   template <class T_CastFrom>
00306 inline
00307 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CastFrom>& src)
00308 :
00309   // A different RefPtr<> will not allow us access to __cpp_object.  We need
00310   // to add a get_underlying() for this, but that would encourage incorrect
00311   // use, so we use the less well-known operator->() accessor:
00312   __cpp_object (src.operator->()),
00313   __ref_count(src.refcount_ptr()),
00314   __ref_mutex(src.refmutex_ptr())
00315 {
00316   if(__cpp_object && __ref_count && __ref_mutex) {
00317     __ref_mutex->lock();
00318     ++(*__ref_count);
00319     __ref_mutex->unlock();
00320   }
00321 }
00322 
00323 template <class T_CppObject> inline
00324 void
00325 RefPtr<T_CppObject>::swap(RefPtr<T_CppObject>& other)
00326 {
00327   T_CppObject *const temp = __cpp_object;
00328   int *temp_count         = __ref_count; 
00329   Mutex *temp_mutex       = __ref_mutex;
00330 
00331   __cpp_object = other.__cpp_object;
00332   __ref_count  = other.__ref_count;
00333   __ref_mutex  = other.__ref_mutex;
00334 
00335   other.__cpp_object = temp;
00336   other.__ref_count  = temp_count;
00337   other.__ref_mutex  = temp_mutex;
00338 }
00339 
00340 template <class T_CppObject> inline
00341 RefPtr<T_CppObject>&
00342 RefPtr<T_CppObject>::operator=(const RefPtr<T_CppObject>& src)
00343 {
00344   // In case you haven't seen the swap() technique to implement copy
00345   // assignment before, here's what it does:
00346   //
00347   // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
00348   //    increasing the reference count of the source object.
00349   //
00350   // 2) Swap the internal object pointers of *this and the temporary
00351   //    RefPtr<>.  After this step, *this already contains the new pointer,
00352   //    and the old pointer is now managed by temp.
00353   //
00354   // 3) The destructor of temp is executed, thereby unreferencing the
00355   //    old object pointer.
00356   //
00357   // This technique is described in Herb Sutter's "Exceptional C++", and
00358   // has a number of advantages over conventional approaches:
00359   //
00360   // - Code reuse by calling the copy ctor.
00361   // - Strong exception safety for free.
00362   // - Self assignment is handled implicitely.
00363   // - Simplicity.
00364   // - It just works and is hard to get wrong; i.e. you can use it without
00365   //   even thinking about it to implement copy assignment whereever the
00366   //   object data is managed indirectly via a pointer, which is very common.
00367 
00368   RefPtr<T_CppObject> temp (src);
00369   this->swap(temp);
00370   return *this;
00371 }
00372 
00373 template <class T_CppObject> inline
00374 RefPtr<T_CppObject>&
00375 RefPtr<T_CppObject>::operator=(T_CppObject *ptr)
00376 {
00377   RefPtr<T_CppObject> temp(ptr);
00378   this->swap(temp);
00379   return *this;
00380 }
00381 
00382 
00383 template <class T_CppObject>
00384   template <class T_CastFrom>
00385 inline
00386 RefPtr<T_CppObject>&
00387 RefPtr<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src)
00388 {
00389   RefPtr<T_CppObject> temp (src);
00390   this->swap(temp);
00391   return *this;
00392 }
00393 
00394 template <class T_CppObject> inline
00395 bool
00396 RefPtr<T_CppObject>::operator==(const RefPtr<T_CppObject>& src) const
00397 {
00398   return (__cpp_object == src.__cpp_object);
00399 }
00400 
00401 template <class T_CppObject> inline
00402 bool
00403 RefPtr<T_CppObject>::operator!=(const RefPtr<T_CppObject>& src) const
00404 {
00405   return (__cpp_object != src.__cpp_object);
00406 }
00407 
00408 template <class T_CppObject> inline
00409 RefPtr<T_CppObject>::operator bool() const
00410 {
00411   return (__cpp_object != 0);
00412 }
00413 
00414 template <class T_CppObject> inline
00415 void RefPtr<T_CppObject>::clear()
00416 {
00417   RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
00418   this->swap(temp);
00419 }
00420 
00421 template <class T_CppObject>
00422   template <class T_CastFrom>
00423 inline
00424 RefPtr<T_CppObject>
00425 RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src)
00426 {
00427   T_CppObject *const cpp_object = dynamic_cast<T_CppObject*>(src.operator->());
00428 
00429   if(cpp_object) //Check whether dynamic_cast<> succeeded so we don't pass a null object with a used refcount:
00430     return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
00431   else
00432     return RefPtr<T_CppObject>();
00433 }
00434 
00435 template <class T_CppObject>
00436   template <class T_CastFrom>
00437 inline
00438 RefPtr<T_CppObject>
00439 RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src)
00440 {
00441   T_CppObject *const cpp_object = static_cast<T_CppObject*>(src.operator->());
00442 
00443   return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
00444 }
00445 
00446 template <class T_CppObject>
00447   template <class T_CastFrom>
00448 inline
00449 RefPtr<T_CppObject>
00450 RefPtr<T_CppObject>::cast_const(const RefPtr<T_CastFrom>& src)
00451 {
00452   T_CppObject *const cpp_object = const_cast<T_CppObject*>(src.operator->());
00453 
00454   return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
00455 }
00456 
00457 
00458 /** Swap refptr instances.
00459  * @param lrp "left" refptr
00460  * @param rrp "right" refptr
00461  * @relates fawkes::RefPtr
00462  */
00463 template <class T_CppObject> inline
00464 void
00465 swap(RefPtr<T_CppObject>& lrp, RefPtr<T_CppObject>& rrp)
00466 {
00467   lrp.swap(rrp);
00468 }
00469 
00470 } // end namespace fawkes
00471 
00472 
00473 #endif

Generated on 1 Mar 2011 for Fawkes API by  doxygen 1.6.1