# 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
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sat Apr 11 13:46:43 2009