OgreSharedPtr.h
Go to the documentation of this file.
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
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Mon Jul 27 2020 13:40:47