- Main Page
- Namespaces
- Classes
- Files

# 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