00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://www.ogre3d.org/ 00006 00007 Copyright (c) 2000-2006 Torus Knot Software Ltd 00008 Also see acknowledgements in Readme.html 00009 00010 This program is free software; you can redistribute it and/or modify it under 00011 the terms of the GNU Lesser General Public License as published by the Free Software 00012 Foundation; either version 2 of the License, or (at your option) any later 00013 version. 00014 00015 This program is distributed in the hope that it will be useful, but WITHOUT 00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License along with 00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00022 http://www.gnu.org/copyleft/lesser.txt. 00023 00024 You may alternatively use this source under the terms of a specific version of 00025 the OGRE Unrestricted License provided you have obtained such a license from 00026 Torus Knot Software Ltd. 00027 ----------------------------------------------------------------------------- 00028 */ 00029 #ifndef __SharedPtr_H__ 00030 #define __SharedPtr_H__ 00031 00032 #include "OgrePrerequisites.h" 00033 00034 namespace Ogre { 00035 00037 enum SharedPtrFreeMethod 00038 { 00040 SPFM_DELETE, 00042 SPFM_DELETE_T, 00044 SPFM_FREE 00045 }; 00046 00055 template<class T> class SharedPtr 00056 { 00057 protected: 00058 T* pRep; 00059 unsigned int* pUseCount; 00060 SharedPtrFreeMethod useFreeMethod; // if we should use OGRE_FREE instead of OGRE_DELETE 00061 public: 00062 OGRE_AUTO_SHARED_MUTEX // public to allow external locking 00067 SharedPtr() : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE) 00068 { 00069 OGRE_SET_AUTO_SHARED_MUTEX_NULL 00070 } 00071 00076 template< class Y> 00077 explicit SharedPtr(Y* rep, SharedPtrFreeMethod freeMethod = SPFM_DELETE) 00078 : pRep(rep) 00079 , pUseCount(rep ? OGRE_NEW_T(unsigned int, MEMCATEGORY_GENERAL)(1) : 0) 00080 , useFreeMethod(freeMethod) 00081 { 00082 OGRE_SET_AUTO_SHARED_MUTEX_NULL 00083 OGRE_NEW_AUTO_SHARED_MUTEX 00084 } 00085 SharedPtr(const SharedPtr& r) 00086 : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE) 00087 { 00088 // lock & copy other mutex pointer 00089 00090 OGRE_SET_AUTO_SHARED_MUTEX_NULL 00091 OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME) 00092 { 00093 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME) 00094 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME) 00095 pRep = r.pRep; 00096 pUseCount = r.pUseCount; 00097 useFreeMethod = r.useFreeMethod; 00098 // Handle zero pointer gracefully to manage STL containers 00099 if(pUseCount) 00100 { 00101 ++(*pUseCount); 00102 } 00103 } 00104 } 00105 SharedPtr& operator=(const SharedPtr& r) { 00106 if (pRep == r.pRep) 00107 return *this; 00108 // Swap current data into a local copy 00109 // this ensures we deal with rhs and this being dependent 00110 SharedPtr<T> tmp(r); 00111 swap(tmp); 00112 return *this; 00113 } 00114 00115 template< class Y> 00116 SharedPtr(const SharedPtr<Y>& r) 00117 : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE) 00118 { 00119 // lock & copy other mutex pointer 00120 00121 OGRE_SET_AUTO_SHARED_MUTEX_NULL 00122 OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME) 00123 { 00124 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME) 00125 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME) 00126 pRep = r.getPointer(); 00127 pUseCount = r.useCountPointer(); 00128 useFreeMethod = r.freeMethod(); 00129 // Handle zero pointer gracefully to manage STL containers 00130 if(pUseCount) 00131 { 00132 ++(*pUseCount); 00133 } 00134 } 00135 } 00136 template< class Y> 00137 SharedPtr& operator=(const SharedPtr<Y>& r) { 00138 if (pRep == r.pRep) 00139 return *this; 00140 // Swap current data into a local copy 00141 // this ensures we deal with rhs and this being dependent 00142 SharedPtr<T> tmp(r); 00143 swap(tmp); 00144 return *this; 00145 } 00146 virtual ~SharedPtr() { 00147 release(); 00148 } 00149 00150 00151 inline T& operator*() const { assert(pRep); return *pRep; } 00152 inline T* operator->() const { assert(pRep); return pRep; } 00153 inline T* get() const { return pRep; } 00154 00159 void bind(T* rep, SharedPtrFreeMethod freeMethod = SPFM_DELETE) { 00160 assert(!pRep && !pUseCount); 00161 OGRE_NEW_AUTO_SHARED_MUTEX 00162 OGRE_LOCK_AUTO_SHARED_MUTEX 00163 pUseCount = OGRE_NEW_T(unsigned int, MEMCATEGORY_GENERAL)(1); 00164 pRep = rep; 00165 useFreeMethod = freeMethod; 00166 } 00167 00168 inline bool unique() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount == 1; } 00169 inline unsigned int useCount() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount; } 00170 inline unsigned int* useCountPointer() const { return pUseCount; } 00171 00172 inline T* getPointer() const { return pRep; } 00173 inline SharedPtrFreeMethod freeMethod() const { return useFreeMethod; } 00174 00175 inline bool isNull(void) const { return pRep == 0; } 00176 00177 inline void setNull(void) { 00178 if (pRep) 00179 { 00180 // can't scope lock mutex before release in case deleted 00181 release(); 00182 pRep = 0; 00183 pUseCount = 0; 00184 } 00185 } 00186 00187 protected: 00188 00189 inline void release(void) 00190 { 00191 bool destroyThis = false; 00192 00193 /* If the mutex is not initialized to a non-zero value, then 00194 neither is pUseCount nor pRep. 00195 */ 00196 00197 OGRE_MUTEX_CONDITIONAL(OGRE_AUTO_MUTEX_NAME) 00198 { 00199 // lock own mutex in limited scope (must unlock before destroy) 00200 OGRE_LOCK_AUTO_SHARED_MUTEX 00201 if (pUseCount) 00202 { 00203 if (--(*pUseCount) == 0) 00204 { 00205 destroyThis = true; 00206 } 00207 } 00208 } 00209 if (destroyThis) 00210 destroy(); 00211 00212 OGRE_SET_AUTO_SHARED_MUTEX_NULL 00213 } 00214 00215 virtual void destroy(void) 00216 { 00217 // IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS 00218 // BEFORE SHUTTING OGRE DOWN 00219 // Use setNull() before shutdown or make sure your pointer goes 00220 // out of scope before OGRE shuts down to avoid this. 00221 switch(useFreeMethod) 00222 { 00223 case SPFM_DELETE: 00224 OGRE_DELETE pRep; 00225 break; 00226 case SPFM_DELETE_T: 00227 OGRE_DELETE_T(pRep, T, MEMCATEGORY_GENERAL); 00228 break; 00229 case SPFM_FREE: 00230 OGRE_FREE(pRep, MEMCATEGORY_GENERAL); 00231 break; 00232 }; 00233 // use OGRE_FREE instead of OGRE_DELETE_T since 'unsigned int' isn't a destructor 00234 // we only used OGRE_NEW_T to be able to use constructor 00235 OGRE_FREE(pUseCount, MEMCATEGORY_GENERAL); 00236 OGRE_DELETE_AUTO_SHARED_MUTEX 00237 } 00238 00239 virtual void swap(SharedPtr<T> &other) 00240 { 00241 std::swap(pRep, other.pRep); 00242 std::swap(pUseCount, other.pUseCount); 00243 std::swap(useFreeMethod, other.useFreeMethod); 00244 #if OGRE_THREAD_SUPPORT 00245 std::swap(OGRE_AUTO_MUTEX_NAME, other.OGRE_AUTO_MUTEX_NAME); 00246 #endif 00247 } 00248 }; 00249 00250 template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b) 00251 { 00252 return a.get() == b.get(); 00253 } 00254 00255 template<class T, class U> inline bool operator!=(SharedPtr<T> const& a, SharedPtr<U> const& b) 00256 { 00257 return a.get() != b.get(); 00258 } 00259 00260 template<class T, class U> inline bool operator<(SharedPtr<T> const& a, SharedPtr<U> const& b) 00261 { 00262 return std::less<const void*>()(a.get(), b.get()); 00263 } 00264 } 00265 00266 00267 00268 #endif
Copyright © 2008 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Sep 27 22:02:26 2009