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 
00071   inline RefPtr(const RefPtr<T_CppObject>& src);
00072 
00077   template <class T_CastFrom>
00078   inline RefPtr(const RefPtr<T_CastFrom>& src);
00079 
00085   inline void swap(RefPtr<T_CppObject>& other);
00086 
00088   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CppObject>& src);
00089 
00094   template <class T_CastFrom>
00095   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CastFrom>& src);
00096 
00098   inline bool operator==(const RefPtr<T_CppObject>& src) const;
00099   
00101   inline bool operator!=(const RefPtr<T_CppObject>& src) const;
00102 
00108   inline T_CppObject* operator->() const;
00109 
00118   inline operator bool() const;
00119 
00121   inline void clear();
00122 
00123 
00131   template <class T_CastFrom>
00132   static inline RefPtr<T_CppObject> cast_dynamic(const RefPtr<T_CastFrom>& src);
00133 
00141   template <class T_CastFrom>
00142   static inline RefPtr<T_CppObject> cast_static(const RefPtr<T_CastFrom>& src);
00143 
00151   template <class T_CastFrom>
00152   static inline RefPtr<T_CppObject> cast_const(const RefPtr<T_CastFrom>& src);
00153 
00154 
00155 #ifndef DOXYGEN_IGNORE_THIS
00156 
00157   // Warning: This is for internal use only.  Do not manually modify the
00158   // reference count with this pointer.
00159   inline int* refcount_() const { return pCppRefcount_; }
00160 
00161 #endif // DOXYGEN_IGNORE_THIS
00162 
00163 private:
00164   void unref();
00165 
00166   T_CppObject* pCppObject_;
00167   mutable int* pCppRefcount_;
00168 };
00169 
00170 
00171 #ifndef DOXYGEN_IGNORE_THIS
00172 
00173 // RefPtr<>::operator->() comes first here since it's used by other methods.
00174 // If it would come after them it wouldn't be inlined.
00175 
00176 template <class T_CppObject> inline
00177 T_CppObject* RefPtr<T_CppObject>::operator->() const
00178 {
00179   return pCppObject_;
00180 }
00181 
00182 template <class T_CppObject> inline
00183 RefPtr<T_CppObject>::RefPtr()
00184 :
00185   pCppObject_(0),
00186   pCppRefcount_(0)
00187 {}
00188 
00189 template <class T_CppObject> inline
00190 RefPtr<T_CppObject>::~RefPtr()
00191 {
00192   unref();
00193 }
00194 
00195 template <class T_CppObject> inline
00196 void RefPtr<T_CppObject>::unref()
00197 {
00198   if(pCppRefcount_)
00199   {
00200     --(*pCppRefcount_);
00201 
00202     if(*pCppRefcount_ == 0)
00203     {
00204       if(pCppObject_)
00205       {
00206         delete pCppObject_;
00207         pCppObject_ = 0;
00208       }
00209 
00210       delete pCppRefcount_;
00211       pCppRefcount_ = 0;
00212     }
00213   }
00214 }
00215 
00216 
00217 template <class T_CppObject> inline
00218 RefPtr<T_CppObject>::RefPtr(T_CppObject* pCppObject)
00219 :
00220   pCppObject_(pCppObject),
00221   pCppRefcount_(0)
00222 {
00223   if(pCppObject)
00224   {
00225     pCppRefcount_ = new int;
00226     *pCppRefcount_ = 1; //This will be decremented in the destructor.
00227   }
00228 }
00229 
00230 template <class T_CppObject> inline
00231 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CppObject>& src)
00232 :
00233   pCppObject_ (src.pCppObject_),
00234   pCppRefcount_(src.pCppRefcount_)
00235 {
00236   if(pCppObject_ && pCppRefcount_)
00237     ++(*pCppRefcount_);
00238 }
00239 
00240 // The templated ctor allows copy construction from any object that's
00241 // castable.  Thus, it does downcasts:
00242 //   base_ref = derived_ref
00243 template <class T_CppObject>
00244   template <class T_CastFrom>
00245 inline
00246 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CastFrom>& src)
00247 :
00248   // A different RefPtr<> will not allow us access to pCppObject_.  We need
00249   // to add a get_underlying() for this, but that would encourage incorrect
00250   // use, so we use the less well-known operator->() accessor:
00251   pCppObject_ (src.operator->()),
00252   pCppRefcount_(src.refcount_())
00253 {
00254   if(pCppObject_ && pCppRefcount_)
00255     ++(*pCppRefcount_);
00256 }
00257 
00258 template <class T_CppObject> inline
00259 void RefPtr<T_CppObject>::swap(RefPtr<T_CppObject>& other)
00260 {
00261   T_CppObject *const temp = pCppObject_;
00262   int* temp_count = pCppRefcount_; 
00263 
00264   pCppObject_ = other.pCppObject_;
00265   pCppRefcount_ = other.pCppRefcount_;
00266 
00267   other.pCppObject_ = temp;
00268   other.pCppRefcount_ = temp_count;
00269 }
00270 
00271 template <class T_CppObject> inline
00272 RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CppObject>& src)
00273 {
00274   // In case you haven't seen the swap() technique to implement copy
00275   // assignment before, here's what it does:
00276   //
00277   // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
00278   //    increasing the reference count of the source object.
00279   //
00280   // 2) Swap the internal object pointers of *this and the temporary
00281   //    RefPtr<>.  After this step, *this already contains the new pointer,
00282   //    and the old pointer is now managed by temp.
00283   //
00284   // 3) The destructor of temp is executed, thereby unreferencing the
00285   //    old object pointer.
00286   //
00287   // This technique is described in Herb Sutter's "Exceptional C++", and
00288   // has a number of advantages over conventional approaches:
00289   //
00290   // - Code reuse by calling the copy ctor.
00291   // - Strong exception safety for free.
00292   // - Self assignment is handled implicitely.
00293   // - Simplicity.
00294   // - It just works and is hard to get wrong; i.e. you can use it without
00295   //   even thinking about it to implement copy assignment whereever the
00296   //   object data is managed indirectly via a pointer, which is very common.
00297 
00298   RefPtr<T_CppObject> temp (src);
00299   this->swap(temp);
00300   return *this;
00301 }
00302 
00303 template <class T_CppObject>
00304   template <class T_CastFrom>
00305 inline
00306 RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src)
00307 {
00308   RefPtr<T_CppObject> temp (src);
00309   this->swap(temp);
00310   return *this;
00311 }
00312 
00313 template <class T_CppObject> inline
00314 bool RefPtr<T_CppObject>::operator==(const RefPtr<T_CppObject>& src) const
00315 {
00316   return (pCppObject_ == src.pCppObject_);
00317 }
00318 
00319 template <class T_CppObject> inline
00320 bool RefPtr<T_CppObject>::operator!=(const RefPtr<T_CppObject>& src) const
00321 {
00322   return (pCppObject_ != src.pCppObject_);
00323 }
00324 
00325 template <class T_CppObject> inline
00326 RefPtr<T_CppObject>::operator bool() const
00327 {
00328   return (pCppObject_ != 0);
00329 }
00330 
00331 template <class T_CppObject> inline
00332 void RefPtr<T_CppObject>::clear()
00333 {
00334   RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
00335   this->swap(temp);
00336 }
00337 
00338 template <class T_CppObject>
00339   template <class T_CastFrom>
00340 inline
00341 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src)
00342 {
00343   T_CppObject *const pCppObject = dynamic_cast<T_CppObject*>(src.operator->());
00344 
00345   if(pCppObject && src.refcount_())
00346     ++(*(src.refcount_()));
00347 
00348   return RefPtr<T_CppObject>(pCppObject); //TODO: Does an unnecessary extra reference() on the C object.
00349 }
00350 
00351 template <class T_CppObject>
00352   template <class T_CastFrom>
00353 inline
00354 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src)
00355 {
00356   T_CppObject *const pCppObject = static_cast<T_CppObject*>(src.operator->());
00357 
00358   if(pCppObject && src.refcount_())
00359     ++(*(src.refcount_()));
00360 
00361   return RefPtr<T_CppObject>(pCppObject); //TODO: Does an unnecessary extra reference() on the C object.
00362 }
00363 
00364 template <class T_CppObject>
00365   template <class T_CastFrom>
00366 inline
00367 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_const(const RefPtr<T_CastFrom>& src)
00368 {
00369   T_CppObject *const pCppObject = const_cast<T_CppObject*>(src.operator->());
00370 
00371   if(pCppObject && src.refcount_())
00372     ++(*(src.refcount_()));
00373 
00374   return RefPtr<T_CppObject>(pCppObject); //TODO: Does an unnecessary extra reference() on the C object.
00375 }
00376 
00377 #endif /* DOXYGEN_IGNORE_THIS */
00378 
00380 template <class T_CppObject> inline
00381 void swap(RefPtr<T_CppObject>& lhs, RefPtr<T_CppObject>& rhs)
00382 {
00383   lhs.swap(rhs);
00384 }
00385 
00386 } // namespace Cairo
00387 
00388 
00389 #endif /* _cairo_REFPTR_H */
00390 
00391 // vim: ts=2 sw=2 et

Generated on Sun Dec 16 19:22:10 2007 for cairomm by  doxygen 1.5.1