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-2013 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 #include "OgreAtomicScalar.h" 00033 00034 namespace Ogre { 00042 00043 enum SharedPtrFreeMethod 00044 { 00046 SPFM_DELETE, 00048 SPFM_DELETE_T, 00050 SPFM_FREE 00051 }; 00052 00053 struct SharedPtrInfo { 00054 inline SharedPtrInfo() 00055 : useCount(1) 00056 {} 00057 00058 virtual ~SharedPtrInfo() {} 00059 00060 AtomicScalar<unsigned> useCount; 00061 }; 00062 00063 template <class T> 00064 class SharedPtrInfoDelete : public SharedPtrInfo 00065 { 00066 T* mObject; 00067 public: 00068 inline SharedPtrInfoDelete(T* o) : mObject(o) {} 00069 00070 virtual ~SharedPtrInfoDelete() 00071 { 00072 OGRE_DELETE mObject; 00073 } 00074 }; 00075 00076 template <class T> 00077 class SharedPtrInfoDeleteT : public SharedPtrInfo 00078 { 00079 T* mObject; 00080 public: 00081 inline SharedPtrInfoDeleteT(T* o) : mObject(o) {} 00082 00083 virtual ~SharedPtrInfoDeleteT() 00084 { 00085 OGRE_DELETE_T(mObject, T, MEMCATEGORY_GENERAL); 00086 } 00087 }; 00088 00089 template <class T> 00090 class SharedPtrInfoFree : public SharedPtrInfo 00091 { 00092 T* mObject; 00093 public: 00094 inline SharedPtrInfoFree(T* o) : mObject(o) {} 00095 00096 virtual ~SharedPtrInfoFree() 00097 { 00098 OGRE_FREE(mObject, MEMCATEGORY_GENERAL); 00099 } 00100 }; 00101 00102 00111 template<class T> class SharedPtr 00112 { 00113 template<typename Y> friend class SharedPtr; 00114 protected: 00115 /* DO NOT ADD MEMBERS TO THIS CLASS! 00116 * 00117 * The average Ogre application has *thousands* of them. Every extra 00118 * member causes extra memory use in general, and causes extra padding 00119 * to be added to a multitude of structures. 00120 * 00121 * Everything you need to do can be acomplished by creatively working 00122 * with the SharedPtrInfo object. 00123 * 00124 * There is no reason for this object to ever have more than two members. 00125 */ 00126 00127 T* pRep; 00128 SharedPtrInfo* pInfo; 00129 00130 SharedPtr(T* rep, SharedPtrInfo* info) : pRep(rep), pInfo(info) 00131 { 00132 } 00133 00134 public: 00139 SharedPtr() : pRep(0), pInfo(0) 00140 {} 00141 00142 private: 00143 static SharedPtrInfo* createInfoForMethod(T* rep, SharedPtrFreeMethod method) 00144 { 00145 switch(method) { 00146 case SPFM_DELETE: return OGRE_NEW_T(SharedPtrInfoDelete<T>, MEMCATEGORY_GENERAL) (rep); 00147 case SPFM_DELETE_T: return OGRE_NEW_T(SharedPtrInfoDeleteT<T>, MEMCATEGORY_GENERAL) (rep); 00148 case SPFM_FREE: return OGRE_NEW_T(SharedPtrInfoFree<T>, MEMCATEGORY_GENERAL) (rep); 00149 } 00150 assert(!"Bad method"); 00151 return 0; 00152 } 00153 public: 00154 00159 template< class Y> 00160 explicit SharedPtr(Y* rep, SharedPtrFreeMethod inFreeMethod = SPFM_DELETE) 00161 : pRep(rep) 00162 , pInfo(rep ? createInfoForMethod(rep, inFreeMethod) : 0) 00163 { 00164 } 00165 00166 SharedPtr(const SharedPtr& r) 00167 : pRep(r.pRep) 00168 , pInfo(r.pInfo) 00169 { 00170 if (pRep) 00171 { 00172 ++pInfo->useCount; 00173 } 00174 } 00175 00176 SharedPtr& operator=(const SharedPtr& r) { 00177 if (pRep == r.pRep) 00178 { 00179 assert(pInfo == r.pInfo); 00180 return *this; 00181 } 00182 // Swap current data into a local copy 00183 // this ensures we deal with rhs and this being dependent 00184 SharedPtr<T> tmp(r); 00185 swap(tmp); 00186 return *this; 00187 } 00188 00189 /* For C++11 compilers, use enable_if to only expose functions when viable 00190 * 00191 * MSVC 2012 and earlier only claim conformance to C++98. This is fortunate, 00192 * because they don't support default template parameters 00193 */ 00194 #if __cplusplus >= 201103L 00195 template<class Y, 00196 class = typename std::enable_if<std::is_convertible<Y*, T*>::value>::type> 00197 #else 00198 template<class Y> 00199 #endif 00200 SharedPtr(const SharedPtr<Y>& r) 00201 : pRep(r.getPointer()) 00202 , pInfo(r.pInfo) 00203 { 00204 if (pRep) 00205 { 00206 ++pInfo->useCount; 00207 } 00208 } 00209 00210 00211 #if __cplusplus >= 201103L 00212 template<class Y, 00213 class = typename std::enable_if<std::is_assignable<T*, Y*>::value>::type> 00214 #else 00215 template<class Y> 00216 #endif 00217 SharedPtr& operator=(const SharedPtr<Y>& r) 00218 { 00219 if (pRep == r.pRep) 00220 return *this; 00221 // Swap current data into a local copy 00222 // this ensures we deal with rhs and this being dependent 00223 SharedPtr<T> tmp(r); 00224 swap(tmp); 00225 return *this; 00226 } 00227 00228 ~SharedPtr() { 00229 release(); 00230 } 00231 00232 00233 template<typename Y> 00234 inline SharedPtr<Y> staticCast() const 00235 { 00236 if(pRep) { 00237 ++pInfo->useCount; 00238 return SharedPtr<Y>(static_cast<Y*>(pRep), pInfo); 00239 } else return SharedPtr<Y>(); 00240 } 00241 00242 template<typename Y> 00243 inline SharedPtr<Y> dynamicCast() const 00244 { 00245 if(pRep) { 00246 Y* rep = dynamic_cast<Y*>(pRep); 00247 ++pInfo->useCount; 00248 return SharedPtr<Y>(rep, pInfo); 00249 } else return SharedPtr<Y>(); 00250 } 00251 00252 inline T& operator*() const { assert(pRep); return *pRep; } 00253 inline T* operator->() const { assert(pRep); return pRep; } 00254 inline T* get() const { return pRep; } 00255 00263 void bind(T* rep, SharedPtrFreeMethod inFreeMethod = SPFM_DELETE) { 00264 assert(!pRep && !pInfo); 00265 pInfo = createInfoForMethod(rep, inFreeMethod); 00266 pRep = rep; 00267 } 00268 00269 inline bool unique() const { assert(pInfo && pInfo->useCount.get()); return pInfo->useCount.get() == 1; } 00270 inline unsigned int useCount() const { assert(pInfo && pInfo->useCount.get()); return pInfo->useCount.get(); } 00271 inline void setUseCount(unsigned value) { assert(pInfo); pInfo->useCount = value; } 00272 00273 inline T* getPointer() const { return pRep; } 00274 00275 inline bool isNull(void) const { return pRep == 0; } 00276 00277 inline void setNull(void) { 00278 if (pRep) 00279 { 00280 release(); 00281 } 00282 } 00283 00284 protected: 00285 00286 inline void release(void) 00287 { 00288 if (pRep) 00289 { 00290 assert(pInfo); 00291 if(--pInfo->useCount == 0) 00292 destroy(); 00293 } 00294 00295 pRep = 0; 00296 pInfo = 0; 00297 } 00298 00303 inline void destroy(void) 00304 { 00305 assert(pRep && pInfo); 00306 OGRE_DELETE_T(pInfo, SharedPtrInfo, MEMCATEGORY_GENERAL); 00307 } 00308 00309 inline void swap(SharedPtr<T> &other) 00310 { 00311 std::swap(pRep, other.pRep); 00312 std::swap(pInfo, other.pInfo); 00313 } 00314 }; 00315 00316 template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b) 00317 { 00318 return a.get() == b.get(); 00319 } 00320 00321 template<class T, class U> inline bool operator!=(SharedPtr<T> const& a, SharedPtr<U> const& b) 00322 { 00323 return a.get() != b.get(); 00324 } 00325 00326 template<class T, class U> inline bool operator<(SharedPtr<T> const& a, SharedPtr<U> const& b) 00327 { 00328 return std::less<const void*>()(a.get(), b.get()); 00329 } 00332 } 00333 00334 00335 00336 #endif
Copyright © 2012 Torus Knot Software Ltd

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Mon Jul 27 2020 13:40:47