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-2009 Torus Knot Software Ltd 00008 00009 Permission is hereby granted, free of charge, to any person obtaining a copy 00010 of this software and associated documentation files (the "Software"), to deal 00011 in the Software without restriction, including without limitation the rights 00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00013 copies of the Software, and to permit persons to whom the Software is 00014 furnished to do so, subject to the following conditions: 00015 00016 The above copyright notice and this permission notice shall be included in 00017 all copies or substantial portions of the Software. 00018 00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00025 THE SOFTWARE. 00026 ----------------------------------------------------------------------------- 00027 */ 00028 #ifndef __SharedPtr_H__ 00029 #define __SharedPtr_H__ 00030 00031 #include "OgrePrerequisites.h" 00032 00033 namespace Ogre { 00041 00042 enum SharedPtrFreeMethod 00043 { 00045 SPFM_DELETE, 00047 SPFM_DELETE_T, 00049 SPFM_FREE 00050 }; 00051 00060 template<class T> class SharedPtr 00061 { 00062 protected: 00063 T* pRep; 00064 unsigned int* pUseCount; 00065 SharedPtrFreeMethod useFreeMethod; // if we should use OGRE_FREE instead of OGRE_DELETE 00066 public: 00067 OGRE_AUTO_SHARED_MUTEX // public to allow external locking 00072 SharedPtr() : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE) 00073 { 00074 OGRE_SET_AUTO_SHARED_MUTEX_NULL 00075 } 00076 00081 template< class Y> 00082 explicit SharedPtr(Y* rep, SharedPtrFreeMethod freeMethod = SPFM_DELETE) 00083 : pRep(rep) 00084 , pUseCount(rep ? OGRE_NEW_T(unsigned int, MEMCATEGORY_GENERAL)(1) : 0) 00085 , useFreeMethod(freeMethod) 00086 { 00087 OGRE_SET_AUTO_SHARED_MUTEX_NULL 00088 OGRE_NEW_AUTO_SHARED_MUTEX 00089 } 00090 SharedPtr(const SharedPtr& r) 00091 : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE) 00092 { 00093 // lock & copy other mutex pointer 00094 00095 OGRE_SET_AUTO_SHARED_MUTEX_NULL 00096 OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME) 00097 { 00098 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME) 00099 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME) 00100 pRep = r.pRep; 00101 pUseCount = r.pUseCount; 00102 useFreeMethod = r.useFreeMethod; 00103 // Handle zero pointer gracefully to manage STL containers 00104 if(pUseCount) 00105 { 00106 ++(*pUseCount); 00107 } 00108 } 00109 } 00110 SharedPtr& operator=(const SharedPtr& r) { 00111 if (pRep == r.pRep) 00112 return *this; 00113 // Swap current data into a local copy 00114 // this ensures we deal with rhs and this being dependent 00115 SharedPtr<T> tmp(r); 00116 swap(tmp); 00117 return *this; 00118 } 00119 00120 template< class Y> 00121 SharedPtr(const SharedPtr<Y>& r) 00122 : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE) 00123 { 00124 // lock & copy other mutex pointer 00125 00126 OGRE_SET_AUTO_SHARED_MUTEX_NULL 00127 OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME) 00128 { 00129 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME) 00130 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME) 00131 pRep = r.getPointer(); 00132 pUseCount = r.useCountPointer(); 00133 useFreeMethod = r.freeMethod(); 00134 // Handle zero pointer gracefully to manage STL containers 00135 if(pUseCount) 00136 { 00137 ++(*pUseCount); 00138 } 00139 } 00140 } 00141 template< class Y> 00142 SharedPtr& operator=(const SharedPtr<Y>& r) { 00143 if (pRep == r.getPointer()) 00144 return *this; 00145 // Swap current data into a local copy 00146 // this ensures we deal with rhs and this being dependent 00147 SharedPtr<T> tmp(r); 00148 swap(tmp); 00149 return *this; 00150 } 00151 virtual ~SharedPtr() { 00152 release(); 00153 } 00154 00155 00156 inline T& operator*() const { assert(pRep); return *pRep; } 00157 inline T* operator->() const { assert(pRep); return pRep; } 00158 inline T* get() const { return pRep; } 00159 00164 void bind(T* rep, SharedPtrFreeMethod freeMethod = SPFM_DELETE) { 00165 assert(!pRep && !pUseCount); 00166 OGRE_NEW_AUTO_SHARED_MUTEX 00167 OGRE_LOCK_AUTO_SHARED_MUTEX 00168 pUseCount = OGRE_NEW_T(unsigned int, MEMCATEGORY_GENERAL)(1); 00169 pRep = rep; 00170 useFreeMethod = freeMethod; 00171 } 00172 00173 inline bool unique() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount == 1; } 00174 inline unsigned int useCount() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount; } 00175 inline unsigned int* useCountPointer() const { return pUseCount; } 00176 00177 inline T* getPointer() const { return pRep; } 00178 inline SharedPtrFreeMethod freeMethod() const { return useFreeMethod; } 00179 00180 inline bool isNull(void) const { return pRep == 0; } 00181 00182 inline void setNull(void) { 00183 if (pRep) 00184 { 00185 // can't scope lock mutex before release in case deleted 00186 release(); 00187 pRep = 0; 00188 pUseCount = 0; 00189 } 00190 } 00191 00192 protected: 00193 00194 inline void release(void) 00195 { 00196 bool destroyThis = false; 00197 00198 /* If the mutex is not initialized to a non-zero value, then 00199 neither is pUseCount nor pRep. 00200 */ 00201 00202 OGRE_MUTEX_CONDITIONAL(OGRE_AUTO_MUTEX_NAME) 00203 { 00204 // lock own mutex in limited scope (must unlock before destroy) 00205 OGRE_LOCK_AUTO_SHARED_MUTEX 00206 if (pUseCount) 00207 { 00208 if (--(*pUseCount) == 0) 00209 { 00210 destroyThis = true; 00211 } 00212 } 00213 } 00214 if (destroyThis) 00215 destroy(); 00216 00217 OGRE_SET_AUTO_SHARED_MUTEX_NULL 00218 } 00219 00220 virtual void destroy(void) 00221 { 00222 // IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS 00223 // BEFORE SHUTTING OGRE DOWN 00224 // Use setNull() before shutdown or make sure your pointer goes 00225 // out of scope before OGRE shuts down to avoid this. 00226 switch(useFreeMethod) 00227 { 00228 case SPFM_DELETE: 00229 OGRE_DELETE pRep; 00230 break; 00231 case SPFM_DELETE_T: 00232 OGRE_DELETE_T(pRep, T, MEMCATEGORY_GENERAL); 00233 break; 00234 case SPFM_FREE: 00235 OGRE_FREE(pRep, MEMCATEGORY_GENERAL); 00236 break; 00237 }; 00238 // use OGRE_FREE instead of OGRE_DELETE_T since 'unsigned int' isn't a destructor 00239 // we only used OGRE_NEW_T to be able to use constructor 00240 OGRE_FREE(pUseCount, MEMCATEGORY_GENERAL); 00241 OGRE_DELETE_AUTO_SHARED_MUTEX 00242 } 00243 00244 virtual void swap(SharedPtr<T> &other) 00245 { 00246 std::swap(pRep, other.pRep); 00247 std::swap(pUseCount, other.pUseCount); 00248 std::swap(useFreeMethod, other.useFreeMethod); 00249 #if OGRE_THREAD_SUPPORT 00250 std::swap(OGRE_AUTO_MUTEX_NAME, other.OGRE_AUTO_MUTEX_NAME); 00251 #endif 00252 } 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 a.get() != b.get(); 00263 } 00264 00265 template<class T, class U> inline bool operator<(SharedPtr<T> const& a, SharedPtr<U> const& b) 00266 { 00267 return std::less<const void*>()(a.get(), b.get()); 00268 } 00271 } 00272 00273 00274 00275 #endif
Copyright © 2008 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Feb 28 21:10:43 2010