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-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
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Feb 28 21:10:43 2010