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-2006 Torus Knot Software Ltd
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 
00024 You may alternatively use this source under the terms of a specific version of
00025 the OGRE Unrestricted License provided you have obtained such a license from
00026 Torus Knot Software Ltd.
00027 -----------------------------------------------------------------------------
00028 */
00029 #ifndef __SharedPtr_H__
00030 #define __SharedPtr_H__
00031 
00032 #include "OgrePrerequisites.h"
00033 
00034 namespace Ogre {
00035 
00037     enum SharedPtrFreeMethod
00038     {
00040         SPFM_DELETE,
00042         SPFM_DELETE_T,
00044         SPFM_FREE
00045     };
00046 
00055     template<class T> class SharedPtr
00056     {
00057     protected:
00058         T* pRep;
00059         unsigned int* pUseCount;
00060         SharedPtrFreeMethod useFreeMethod; // if we should use OGRE_FREE instead of OGRE_DELETE
00061     public:
00062         OGRE_AUTO_SHARED_MUTEX // public to allow external locking
00067         SharedPtr() : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE)
00068         {
00069             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00070         }
00071 
00076         template< class Y>
00077         explicit SharedPtr(Y* rep, SharedPtrFreeMethod freeMethod = SPFM_DELETE) 
00078             : pRep(rep)
00079             , pUseCount(rep ? OGRE_NEW_T(unsigned int, MEMCATEGORY_GENERAL)(1) : 0)
00080             , useFreeMethod(freeMethod)
00081         {
00082             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00083             OGRE_NEW_AUTO_SHARED_MUTEX
00084         }
00085         SharedPtr(const SharedPtr& r)
00086             : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE)
00087         {
00088             // lock & copy other mutex pointer
00089             
00090             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00091             OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
00092             {
00093                 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
00094                 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
00095                 pRep = r.pRep;
00096                 pUseCount = r.pUseCount; 
00097                 useFreeMethod = r.useFreeMethod;
00098                 // Handle zero pointer gracefully to manage STL containers
00099                 if(pUseCount)
00100                 {
00101                     ++(*pUseCount); 
00102                 }
00103             }
00104         }
00105         SharedPtr& operator=(const SharedPtr& r) {
00106             if (pRep == r.pRep)
00107                 return *this;
00108             // Swap current data into a local copy
00109             // this ensures we deal with rhs and this being dependent
00110             SharedPtr<T> tmp(r);
00111             swap(tmp);
00112             return *this;
00113         }
00114         
00115         template< class Y>
00116         SharedPtr(const SharedPtr<Y>& r)
00117             : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE)
00118         {
00119             // lock & copy other mutex pointer
00120 
00121             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00122             OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
00123             {
00124                 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
00125                 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
00126                 pRep = r.getPointer();
00127                 pUseCount = r.useCountPointer();
00128                 useFreeMethod = r.freeMethod();
00129                 // Handle zero pointer gracefully to manage STL containers
00130                 if(pUseCount)
00131                 {
00132                     ++(*pUseCount);
00133                 }
00134             }
00135         }
00136         template< class Y>
00137         SharedPtr& operator=(const SharedPtr<Y>& r) {
00138             if (pRep == r.pRep)
00139                 return *this;
00140             // Swap current data into a local copy
00141             // this ensures we deal with rhs and this being dependent
00142             SharedPtr<T> tmp(r);
00143             swap(tmp);
00144             return *this;
00145         }
00146         virtual ~SharedPtr() {
00147             release();
00148         }
00149 
00150 
00151         inline T& operator*() const { assert(pRep); return *pRep; }
00152         inline T* operator->() const { assert(pRep); return pRep; }
00153         inline T* get() const { return pRep; }
00154 
00159         void bind(T* rep, SharedPtrFreeMethod freeMethod = SPFM_DELETE) {
00160             assert(!pRep && !pUseCount);
00161             OGRE_NEW_AUTO_SHARED_MUTEX
00162             OGRE_LOCK_AUTO_SHARED_MUTEX
00163             pUseCount = OGRE_NEW_T(unsigned int, MEMCATEGORY_GENERAL)(1);
00164             pRep = rep;
00165             useFreeMethod = freeMethod;
00166         }
00167 
00168         inline bool unique() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount == 1; }
00169         inline unsigned int useCount() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount; }
00170         inline unsigned int* useCountPointer() const { return pUseCount; }
00171 
00172         inline T* getPointer() const { return pRep; }
00173         inline SharedPtrFreeMethod freeMethod() const { return useFreeMethod; }
00174 
00175         inline bool isNull(void) const { return pRep == 0; }
00176 
00177         inline void setNull(void) { 
00178             if (pRep)
00179             {
00180                 // can't scope lock mutex before release in case deleted
00181                 release();
00182                 pRep = 0;
00183                 pUseCount = 0;
00184             }
00185         }
00186 
00187     protected:
00188 
00189         inline void release(void)
00190         {
00191             bool destroyThis = false;
00192 
00193             /* If the mutex is not initialized to a non-zero value, then
00194                neither is pUseCount nor pRep.
00195              */
00196 
00197             OGRE_MUTEX_CONDITIONAL(OGRE_AUTO_MUTEX_NAME)
00198             {
00199                 // lock own mutex in limited scope (must unlock before destroy)
00200                 OGRE_LOCK_AUTO_SHARED_MUTEX
00201                 if (pUseCount)
00202                 {
00203                     if (--(*pUseCount) == 0) 
00204                     {
00205                         destroyThis = true;
00206                     }
00207                 }
00208             }
00209             if (destroyThis)
00210                 destroy();
00211 
00212             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00213         }
00214 
00215         virtual void destroy(void)
00216         {
00217             // IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS
00218             // BEFORE SHUTTING OGRE DOWN
00219             // Use setNull() before shutdown or make sure your pointer goes
00220             // out of scope before OGRE shuts down to avoid this.
00221             switch(useFreeMethod)
00222             {
00223             case SPFM_DELETE:
00224                 OGRE_DELETE pRep;
00225                 break;
00226             case SPFM_DELETE_T:
00227                 OGRE_DELETE_T(pRep, T, MEMCATEGORY_GENERAL);
00228                 break;
00229             case SPFM_FREE:
00230                 OGRE_FREE(pRep, MEMCATEGORY_GENERAL);
00231                 break;
00232             };
00233             // use OGRE_FREE instead of OGRE_DELETE_T since 'unsigned int' isn't a destructor
00234             // we only used OGRE_NEW_T to be able to use constructor
00235             OGRE_FREE(pUseCount, MEMCATEGORY_GENERAL);
00236             OGRE_DELETE_AUTO_SHARED_MUTEX
00237         }
00238 
00239         virtual void swap(SharedPtr<T> &other) 
00240         {
00241             std::swap(pRep, other.pRep);
00242             std::swap(pUseCount, other.pUseCount);
00243             std::swap(useFreeMethod, other.useFreeMethod);
00244 #if OGRE_THREAD_SUPPORT
00245             std::swap(OGRE_AUTO_MUTEX_NAME, other.OGRE_AUTO_MUTEX_NAME);
00246 #endif
00247         }
00248     };
00249 
00250     template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b)
00251     {
00252         return a.get() == b.get();
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 std::less<const void*>()(a.get(), b.get());
00263     }
00264 }
00265 
00266 
00267 
00268 #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 Sep 27 22:02:26 2009