# 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 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 © 2008 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Sun May 8 2011 20:28:09