bakery 2.6
|
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