Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

sharedptr.h

Go to the documentation of this file.
00001 /*
00002  * Copyright 2004 Murray Cumming
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the Free
00016  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018  
00019 #ifndef BAKERY_UTILITIES_SHAREDPTR_H
00020 #define BAKERY_UTILITIES_SHAREDPTR_H
00021 
00022 #include <iostream> //Just for debugging.
00023 
00024 namespace Bakery
00025 {
00026 
00030 template< typename T_obj >
00031 class sharedptr
00032 {
00033 public:
00034   typedef size_t size_type;
00035 
00037   sharedptr();
00038 
00040   explicit sharedptr(T_obj* pobj);
00041 
00043   sharedptr(const sharedptr& src);
00044 
00046   sharedptr& operator=(const sharedptr& src);
00047 
00048   virtual ~sharedptr();
00049 
00052   inline T_obj& operator*();
00053 
00056   inline const T_obj& operator*() const;
00057 
00065   inline T_obj* operator->() const;
00066 
00075   inline operator bool() const;
00076 
00078   inline T_obj* obj();
00079 
00081   inline const T_obj* obj() const;
00082 
00083 
00084 protected:
00085   inline void ref();
00086   inline void unref();
00087 
00088   size_type* m_pRefCount; //Shared between instances, by copying.
00089   T_obj* m_pobj; //The underlying instance.
00090 };
00091 
00092 template< typename T_obj>
00093 sharedptr<T_obj>::sharedptr()
00094 : m_pRefCount(0), m_pobj(0)
00095 {
00096 
00097 }
00098 
00099 template< typename T_obj>
00100 sharedptr<T_obj>::sharedptr(T_obj* pobj)
00101 : m_pRefCount(0), m_pobj(pobj)
00102 {
00103     //Start refcounting:
00104     ref();
00105 }
00106 
00107 template< typename T_obj>
00108 sharedptr<T_obj>::sharedptr(const sharedptr<T_obj>& src)
00109 : m_pRefCount(src.m_pRefCount), m_pobj(src.m_pobj)
00110 {
00111     ref();
00112 }
00113 
00114 template< typename T_obj>
00115 sharedptr<T_obj>& sharedptr<T_obj>::operator=(const sharedptr<T_obj>& src)
00116 {
00117   //std::cout << "sharedptr& operator=(const sharedptr& src)" << std::endl;
00118   if(&src != this)
00119   {
00120     //Unref any existing stuff.
00121     //operator= can never run before a constructor, so these values will be initialized already.
00122     if(m_pobj) //The if() might not be required.
00123     {
00124       unref(); //Could cause a deallocation.
00125     }
00126 
00127     //Copy:
00128     m_pobj = src.m_pobj;
00129 
00130     m_pRefCount = src.m_pRefCount;
00131     ref();
00132   }
00133 
00134   return *this;
00135 }
00136 
00137 template< typename T_obj>
00138 sharedptr<T_obj>::~sharedptr()
00139 {
00140    unref();
00141 }
00142 
00143 /*
00144 template< typename T_obj>
00145 void sharedptr<T_obj>::clear_without_deallocating()
00146 {
00147   m_pobj = 0;
00148 }
00149 */
00150 
00151 template< typename T_obj>
00152 inline
00153 T_obj* sharedptr<T_obj>::obj()
00154 {
00155   return m_pobj;
00156 }
00157 
00158 template< typename T_obj>
00159 inline
00160 const T_obj* sharedptr<T_obj>::obj() const
00161 {
00162   return m_pobj;
00163 }
00164 
00165 template< typename T_obj>
00166 inline
00167 T_obj& sharedptr<T_obj>::operator*()
00168 {
00169   return *m_pobj;
00170 }
00171 
00172 template< typename T_obj>
00173 inline
00174 const T_obj& sharedptr<T_obj>::operator*() const
00175 {
00176   return *m_pobj;
00177 }
00178 
00179 template< typename T_obj>
00180 inline
00181 T_obj* sharedptr<T_obj>::operator->() const
00182 {
00183   return m_pobj;
00184 }
00185 
00186 template <class T_obj>
00187 inline
00188 sharedptr<T_obj>::operator bool() const
00189 {
00190   return (m_pobj != 0);
00191 }
00192 
00193 
00194 template <class T_obj>
00195 inline
00196 void sharedptr<T_obj>::ref()
00197 {
00198   if(m_pobj) //Don't waste time on invalid instances. These would be very rare anyway, and intentionally created with (0,0) construction.
00199   {
00200     if(m_pRefCount == 0)
00201     {
00202       //std::cout << "sharedptr::ref(): first ref" << std::endl;
00203       //First ref, so allocate the shared count:
00204       m_pRefCount = new size_type();
00205       *m_pRefCount = 1;
00206     }
00207     else
00208     {
00209       //std::cout << "sharedptr::ref(): starting at" << *m_pRefCount << std::endl;
00210       (*m_pRefCount)++;
00211     }
00212   }
00213 }
00214 
00215 template <class T_obj>
00216 inline
00217 void sharedptr<T_obj>::unref()
00218 {
00219   if(m_pRefCount)
00220   {
00221     //std::cout << "sharedptr::unref(): starting at " << *m_pRefCount << std::endl;
00222 
00223     if( (*m_pRefCount) > 0 )
00224        (*m_pRefCount)--;
00225 
00226     //Unalloc if this is the last user of the obj:
00227     if(*m_pRefCount == 0)
00228     {
00229       if(m_pobj)
00230        {
00231          //try
00232          //{
00233            //std::cout << "sharedptr::unref(): deallocating " << *m_pRefCount << std::endl;
00234            delete m_pobj;
00235            m_pobj = 0;
00236          //}
00237          /*
00238          catch(ex_base&)
00239          {
00240           //std::cout << "sharedptr::unref(): exception thrown during deallocation." << std::endl;
00241            //Ignore it. Can't throw an expection up to the destructor.
00242          }
00243          */
00244 
00245          m_pobj = 0;
00246       }
00247 
00248        //Clear ref count:
00249        delete m_pRefCount;
00250        m_pRefCount = 0;
00251     }
00252   }
00253   else
00254   {
00255     //std::cout << "sharedptr::unref(): ref not setup." << std::endl;
00256   }
00257 
00258 }
00259 
00260 
00261 } //namespace
00262 
00263 #endif //BAKERY_UTILITIES_SHAREDPTR_H
00264 

Generated on Tue Jan 4 19:00:08 2005 for bakery by  doxygen 1.3.9.1