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-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
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Fri May 25 23:36:27 2012