refptr.h

Go to the documentation of this file.
00001 // -*- c++ -*-
00002 #ifndef _cairo_REFPTR_H
00003 #define _cairo_REFPTR_H
00004 
00005 /* $Id: refptr.h,v 1.6 2006-09-27 18:38:57 murrayc Exp $ */
00006 
00007 /* Copyright 2005 The cairomm Development Team
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Library General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Library General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Library General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00022  * 02110-1301, USA.
00023  */
00024 
00025 
00026 namespace Cairo
00027 {
00028 
00041 template <class T_CppObject>
00042 class RefPtr
00043 {
00044 public:
00049   inline RefPtr();
00050   
00052   inline ~RefPtr();
00053 
00065   explicit inline RefPtr(T_CppObject* pCppObject);
00066 
00068   explicit inline RefPtr(T_CppObject* pCppObject, int* refcount);
00069 
00074   inline RefPtr(const RefPtr<T_CppObject>& src);
00075 
00080   template <class T_CastFrom>
00081   inline RefPtr(const RefPtr<T_CastFrom>& src);
00082 
00088   inline void swap(RefPtr<T_CppObject>& other);
00089 
00091   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CppObject>& src);
00092 
00097   template <class T_CastFrom>
00098   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CastFrom>& src);
00099 
00101   inline bool operator==(const RefPtr<T_CppObject>& src) const;
00102   
00104   inline bool operator!=(const RefPtr<T_CppObject>& src) const;
00105 
00111   inline T_CppObject* operator->() const;
00112 
00121   inline operator bool() const;
00122 
00124   inline void clear();
00125 
00126 
00134   template <class T_CastFrom>
00135   static inline RefPtr<T_CppObject> cast_dynamic(const RefPtr<T_CastFrom>& src);
00136 
00144   template <class T_CastFrom>
00145   static inline RefPtr<T_CppObject> cast_static(const RefPtr<T_CastFrom>& src);
00146 
00154   template <class T_CastFrom>
00155   static inline RefPtr<T_CppObject> cast_const(const RefPtr<T_CastFrom>& src);
00156 
00157 
00158 #ifndef DOXYGEN_IGNORE_THIS
00159 
00160   // Warning: This is for internal use only.  Do not manually modify the
00161   // reference count with this pointer.
00162   inline int* refcount_() const { return pCppRefcount_; }
00163 
00164 #endif // DOXYGEN_IGNORE_THIS
00165 
00166 private:
00167   void unref();
00168 
00169   T_CppObject* pCppObject_;
00170   mutable int* pCppRefcount_;
00171 };
00172 
00173 
00174 #ifndef DOXYGEN_IGNORE_THIS
00175 
00176 // RefPtr<>::operator->() comes first here since it's used by other methods.
00177 // If it would come after them it wouldn't be inlined.
00178 
00179 template <class T_CppObject> inline
00180 T_CppObject* RefPtr<T_CppObject>::operator->() const
00181 {
00182   return pCppObject_;
00183 }
00184 
00185 template <class T_CppObject> inline
00186 RefPtr<T_CppObject>::RefPtr()
00187 :
00188   pCppObject_(0),
00189   pCppRefcount_(0)
00190 {}
00191 
00192 template <class T_CppObject> inline
00193 RefPtr<T_CppObject>::~RefPtr()
00194 {
00195   unref();
00196 }
00197 
00198 template <class T_CppObject> inline
00199 void RefPtr<T_CppObject>::unref()
00200 {
00201   if(pCppRefcount_)
00202   {
00203     --(*pCppRefcount_);
00204 
00205     if(*pCppRefcount_ == 0)
00206     {
00207       if(pCppObject_)
00208       {
00209         delete pCppObject_;
00210         pCppObject_ = 0;
00211       }
00212 
00213       delete pCppRefcount_;
00214       pCppRefcount_ = 0;
00215     }
00216   }
00217 }
00218 
00219 
00220 template <class T_CppObject> inline
00221 RefPtr<T_CppObject>::RefPtr(T_CppObject* pCppObject)
00222 :
00223   pCppObject_(pCppObject),
00224   pCppRefcount_(0)
00225 {
00226   if(pCppObject)
00227   {
00228     pCppRefcount_ = new int;
00229     *pCppRefcount_ = 1; //This will be decremented in the destructor.
00230   }
00231 }
00232 
00233 //Used by cast_*() implementations:
00234 template <class T_CppObject> inline
00235 RefPtr<T_CppObject>::RefPtr(T_CppObject* pCppObject, int* refcount)
00236 :
00237   pCppObject_(pCppObject),
00238   pCppRefcount_(refcount)
00239 {
00240   if(pCppObject_ && pCppRefcount_)
00241     ++(*pCppRefcount_);
00242 }
00243 
00244 template <class T_CppObject> inline
00245 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CppObject>& src)
00246 :
00247   pCppObject_ (src.pCppObject_),
00248   pCppRefcount_(src.pCppRefcount_)
00249 {
00250   if(pCppObject_ && pCppRefcount_)
00251     ++(*pCppRefcount_);
00252 }
00253 
00254 // The templated ctor allows copy construction from any object that's
00255 // castable.  Thus, it does downcasts:
00256 //   base_ref = derived_ref
00257 template <class T_CppObject>
00258   template <class T_CastFrom>
00259 inline
00260 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CastFrom>& src)
00261 :
00262   // A different RefPtr<> will not allow us access to pCppObject_.  We need
00263   // to add a get_underlying() for this, but that would encourage incorrect
00264   // use, so we use the less well-known operator->() accessor:
00265   pCppObject_ (src.operator->()),
00266   pCppRefcount_(src.refcount_())
00267 {
00268   if(pCppObject_ && pCppRefcount_)
00269     ++(*pCppRefcount_);
00270 }
00271 
00272 template <class T_CppObject> inline
00273 void RefPtr<T_CppObject>::swap(RefPtr<T_CppObject>& other)
00274 {
00275   T_CppObject *const temp = pCppObject_;
00276   int* temp_count = pCppRefcount_; 
00277 
00278   pCppObject_ = other.pCppObject_;
00279   pCppRefcount_ = other.pCppRefcount_;
00280 
00281   other.pCppObject_ = temp;
00282   other.pCppRefcount_ = temp_count;
00283 }
00284 
00285 template <class T_CppObject> inline
00286 RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CppObject>& src)
00287 {
00288   // In case you haven't seen the swap() technique to implement copy
00289   // assignment before, here's what it does:
00290   //
00291   // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
00292   //    increasing the reference count of the source object.
00293   //
00294   // 2) Swap the internal object pointers of *this and the temporary
00295   //    RefPtr<>.  After this step, *this already contains the new pointer,
00296   //    and the old pointer is now managed by temp.
00297   //
00298   // 3) The destructor of temp is executed, thereby unreferencing the
00299   //    old object pointer.
00300   //
00301   // This technique is described in Herb Sutter's "Exceptional C++", and
00302   // has a number of advantages over conventional approaches:
00303   //
00304   // - Code reuse by calling the copy ctor.
00305   // - Strong exception safety for free.
00306   // - Self assignment is handled implicitely.
00307   // - Simplicity.
00308   // - It just works and is hard to get wrong; i.e. you can use it without
00309   //   even thinking about it to implement copy assignment whereever the
00310   //   object data is managed indirectly via a pointer, which is very common.
00311 
00312   RefPtr<T_CppObject> temp (src);
00313   this->swap(temp);
00314   return *this;
00315 }
00316 
00317 template <class T_CppObject>
00318   template <class T_CastFrom>
00319 inline
00320 RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src)
00321 {
00322   RefPtr<T_CppObject> temp (src);
00323   this->swap(temp);
00324   return *this;
00325 }
00326 
00327 template <class T_CppObject> inline
00328 bool RefPtr<T_CppObject>::operator==(const RefPtr<T_CppObject>& src) const
00329 {
00330   return (pCppObject_ == src.pCppObject_);
00331 }
00332 
00333 template <class T_CppObject> inline
00334 bool RefPtr<T_CppObject>::operator!=(const RefPtr<T_CppObject>& src) const
00335 {
00336   return (pCppObject_ != src.pCppObject_);
00337 }
00338 
00339 template <class T_CppObject> inline
00340 RefPtr<T_CppObject>::operator bool() const
00341 {
00342   return (pCppObject_ != 0);
00343 }
00344 
00345 template <class T_CppObject> inline
00346 void RefPtr<T_CppObject>::clear()
00347 {
00348   RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
00349   this->swap(temp);
00350 }
00351 
00352 template <class T_CppObject>
00353   template <class T_CastFrom>
00354 inline
00355 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src)
00356 {
00357   T_CppObject *const pCppObject = dynamic_cast<T_CppObject*>(src.operator->());
00358 
00359   if(pCppObject) //Check whether dynamic_cast<> succeeded so we don't pass a null object with a used refcount:
00360     return RefPtr<T_CppObject>(pCppObject, src.refcount_());
00361   else
00362     return RefPtr<T_CppObject>();
00363 }
00364 
00365 template <class T_CppObject>
00366   template <class T_CastFrom>
00367 inline
00368 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src)
00369 {
00370   T_CppObject *const pCppObject = static_cast<T_CppObject*>(src.operator->());
00371 
00372   return RefPtr<T_CppObject>(pCppObject, src.refcount_());
00373 }
00374 
00375 template <class T_CppObject>
00376   template <class T_CastFrom>
00377 inline
00378 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_const(const RefPtr<T_CastFrom>& src)
00379 {
00380   T_CppObject *const pCppObject = const_cast<T_CppObject*>(src.operator->());
00381 
00382   return RefPtr<T_CppObject>(pCppObject, src.refcount_());
00383 }
00384 
00385 #endif /* DOXYGEN_IGNORE_THIS */
00386 
00388 template <class T_CppObject> inline
00389 void swap(RefPtr<T_CppObject>& lhs, RefPtr<T_CppObject>& rhs)
00390 {
00391   lhs.swap(rhs);
00392 }
00393 
00394 } // namespace Cairo
00395 
00396 
00397 #endif /* _cairo_REFPTR_H */
00398 
00399 // vim: ts=2 sw=2 et

Generated on Thu Sep 4 21:57:13 2008 for cairomm by  doxygen 1.5.5