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-2012 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 inFreeMethod = SPFM_DELETE) 00083 : pRep(rep) 00084 , pUseCount(rep ? OGRE_NEW_T(unsigned int, MEMCATEGORY_GENERAL)(1) : 0) 00085 , useFreeMethod(inFreeMethod) 00086 { 00087 OGRE_SET_AUTO_SHARED_MUTEX_NULL 00088 if (rep) 00089 { 00090 OGRE_NEW_AUTO_SHARED_MUTEX 00091 } 00092 } 00093 SharedPtr(const SharedPtr& r) 00094 : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE) 00095 { 00096 // lock & copy other mutex pointer 00097 00098 OGRE_SET_AUTO_SHARED_MUTEX_NULL 00099 OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME) 00100 { 00101 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME) 00102 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME) 00103 pRep = r.pRep; 00104 pUseCount = r.pUseCount; 00105 useFreeMethod = r.useFreeMethod; 00106 // Handle zero pointer gracefully to manage STL containers 00107 if(pUseCount) 00108 { 00109 ++(*pUseCount); 00110 } 00111 } 00112 } 00113 SharedPtr& operator=(const SharedPtr& r) { 00114 if (pRep == r.pRep) 00115 return *this; 00116 // Swap current data into a local copy 00117 // this ensures we deal with rhs and this being dependent 00118 SharedPtr<T> tmp(r); 00119 swap(tmp); 00120 return *this; 00121 } 00122 00123 template< class Y> 00124 SharedPtr(const SharedPtr<Y>& r) 00125 : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE) 00126 { 00127 // lock & copy other mutex pointer 00128 00129 OGRE_SET_AUTO_SHARED_MUTEX_NULL 00130 OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME) 00131 { 00132 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME) 00133 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME) 00134 pRep = r.getPointer(); 00135 pUseCount = r.useCountPointer(); 00136 useFreeMethod = r.freeMethod(); 00137 // Handle zero pointer gracefully to manage STL containers 00138 if(pUseCount) 00139 { 00140 ++(*pUseCount); 00141 } 00142 } 00143 } 00144 template< class Y> 00145 SharedPtr& operator=(const SharedPtr<Y>& r) { 00146 if (pRep == r.getPointer()) 00147 return *this; 00148 // Swap current data into a local copy 00149 // this ensures we deal with rhs and this being dependent 00150 SharedPtr<T> tmp(r); 00151 swap(tmp); 00152 return *this; 00153 } 00154 virtual ~SharedPtr() { 00155 release(); 00156 } 00157 00158 00159 inline T& operator*() const { assert(pRep); return *pRep; } 00160 inline T* operator->() const { assert(pRep); return pRep; } 00161 inline T* get() const { return pRep; } 00162 00167 void bind(T* rep, SharedPtrFreeMethod inFreeMethod = SPFM_DELETE) { 00168 assert(!pRep && !pUseCount); 00169 OGRE_NEW_AUTO_SHARED_MUTEX 00170 OGRE_LOCK_AUTO_SHARED_MUTEX 00171 pUseCount = OGRE_NEW_T(unsigned int, MEMCATEGORY_GENERAL)(1); 00172 pRep = rep; 00173 useFreeMethod = inFreeMethod; 00174 } 00175 00176 inline bool unique() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount == 1; } 00177 inline unsigned int useCount() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount; } 00178 inline unsigned int* useCountPointer() const { return pUseCount; } 00179 00180 inline T* getPointer() const { return pRep; } 00181 inline SharedPtrFreeMethod freeMethod() const { return useFreeMethod; } 00182 00183 inline bool isNull(void) const { return pRep == 0; } 00184 00185 inline void setNull(void) { 00186 if (pRep) 00187 { 00188 // can't scope lock mutex before release in case deleted 00189 release(); 00190 pRep = 0; 00191 pUseCount = 0; 00192 } 00193 } 00194 00195 protected: 00196 00197 inline void release(void) 00198 { 00199 bool destroyThis = false; 00200 00201 /* If the mutex is not initialized to a non-zero value, then 00202 neither is pUseCount nor pRep. 00203 */ 00204 00205 OGRE_MUTEX_CONDITIONAL(OGRE_AUTO_MUTEX_NAME) 00206 { 00207 // lock own mutex in limited scope (must unlock before destroy) 00208 OGRE_LOCK_AUTO_SHARED_MUTEX 00209 if (pUseCount) 00210 { 00211 if (--(*pUseCount) == 0) 00212 { 00213 destroyThis = true; 00214 } 00215 } 00216 } 00217 if (destroyThis) 00218 destroy(); 00219 00220 OGRE_SET_AUTO_SHARED_MUTEX_NULL 00221 } 00222 00223 virtual void destroy(void) 00224 { 00225 // IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS 00226 // BEFORE SHUTTING OGRE DOWN 00227 // Use setNull() before shutdown or make sure your pointer goes 00228 // out of scope before OGRE shuts down to avoid this. 00229 switch(useFreeMethod) 00230 { 00231 case SPFM_DELETE: 00232 OGRE_DELETE pRep; 00233 break; 00234 case SPFM_DELETE_T: 00235 OGRE_DELETE_T(pRep, T, MEMCATEGORY_GENERAL); 00236 break; 00237 case SPFM_FREE: 00238 OGRE_FREE(pRep, MEMCATEGORY_GENERAL); 00239 break; 00240 }; 00241 // use OGRE_FREE instead of OGRE_DELETE_T since 'unsigned int' isn't a destructor 00242 // we only used OGRE_NEW_T to be able to use constructor 00243 OGRE_FREE(pUseCount, MEMCATEGORY_GENERAL); 00244 OGRE_DELETE_AUTO_SHARED_MUTEX 00245 } 00246 00247 virtual void swap(SharedPtr<T> &other) 00248 { 00249 std::swap(pRep, other.pRep); 00250 std::swap(pUseCount, other.pUseCount); 00251 std::swap(useFreeMethod, other.useFreeMethod); 00252 #if OGRE_THREAD_SUPPORT 00253 std::swap(OGRE_AUTO_MUTEX_NAME, other.OGRE_AUTO_MUTEX_NAME); 00254 #endif 00255 } 00256 }; 00257 00258 template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b) 00259 { 00260 return a.get() == b.get(); 00261 } 00262 00263 template<class T, class U> inline bool operator!=(SharedPtr<T> const& a, SharedPtr<U> const& b) 00264 { 00265 return a.get() != b.get(); 00266 } 00267 00268 template<class T, class U> inline bool operator<(SharedPtr<T> const& a, SharedPtr<U> const& b) 00269 { 00270 return std::less<const void*>()(a.get(), b.get()); 00271 } 00274 } 00275 00276 00277 00278 #endif
Copyright © 2012 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Fri May 25 23:36:27 2012