# 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