Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

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-2005 The OGRE Team
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 */
00025 #ifndef __SharedPtr_H__
00026 #define __SharedPtr_H__
00027 
00028 #include "OgrePrerequisites.h"
00029 
00030 namespace Ogre {
00031 
00044     template<class T> class SharedPtr {
00045     protected:
00046         T* pRep;
00047         unsigned int* pUseCount;
00048     public:
00049         OGRE_AUTO_SHARED_MUTEX // public to allow external locking
00054         SharedPtr() : pRep(0), pUseCount(0)
00055         {
00056             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00057         }
00058 
00059         explicit SharedPtr(T* rep) : pRep(rep), pUseCount(new unsigned int(1))
00060         {
00061             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00062             OGRE_NEW_AUTO_SHARED_MUTEX
00063         }
00064         SharedPtr(const SharedPtr& r)
00065             : pRep(0), pUseCount(0)
00066         {
00067             // lock & copy other mutex pointer
00068             
00069             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00070             OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
00071             {
00072                 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
00073                 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
00074                 pRep = r.pRep;
00075                 pUseCount = r.pUseCount; 
00076                 // Handle zero pointer gracefully to manage STL containers
00077                 if(pUseCount)
00078                 {
00079                     ++(*pUseCount); 
00080                 }
00081             }
00082         }
00083         SharedPtr& operator=(const SharedPtr& r) {
00084             if (pRep == r.pRep)
00085                 return *this;
00086             release();
00087             // lock & copy other mutex pointer
00088             OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
00089             {
00090                 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
00091                 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
00092                 pRep = r.pRep;
00093                 pUseCount = r.pUseCount;
00094                 if (pUseCount)
00095                 {
00096                     ++(*pUseCount);
00097                 }
00098             }
00099             return *this;
00100         }
00101         virtual ~SharedPtr() {
00102             release();
00103         }
00104 
00105 
00106         inline T& operator*() const { assert(pRep); return *pRep; }
00107         inline T* operator->() const { assert(pRep); return pRep; }
00108         inline T* get() const { return pRep; }
00109 
00114         void bind(T* rep) {
00115             assert(!pRep && !pUseCount);
00116             OGRE_NEW_AUTO_SHARED_MUTEX
00117             OGRE_LOCK_AUTO_SHARED_MUTEX
00118             pUseCount = new unsigned int(1);
00119             pRep = rep;
00120         }
00121 
00122         inline bool unique() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount == 1; }
00123         inline unsigned int useCount() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount; }
00124         inline unsigned int* useCountPointer() const { return pUseCount; }
00125 
00126         inline T* getPointer() const { return pRep; }
00127 
00128         inline bool isNull(void) const { return pRep == 0; }
00129 
00130         inline void setNull(void) { 
00131             if (pRep)
00132             {
00133                 // can't scope lock mutex before release incase deleted
00134                 release();
00135                 pRep = 0;
00136                 pUseCount = 0;
00137             }
00138         }
00139 
00140     protected:
00141 
00142         inline void release(void)
00143         {
00144             bool destroyThis = false;
00145 
00146             /* If the mutex is not initialized to a non-zero value, then
00147                neither is pUseCount nor pRep.
00148              */
00149 
00150             OGRE_MUTEX_CONDITIONAL(OGRE_AUTO_MUTEX_NAME)
00151             {
00152                 // lock own mutex in limited scope (must unlock before destroy)
00153                 OGRE_LOCK_AUTO_SHARED_MUTEX
00154                 if (pUseCount)
00155                 {
00156                     if (--(*pUseCount) == 0) 
00157                     {
00158                         destroyThis = true;
00159                     }
00160                 }
00161             }
00162             if (destroyThis)
00163                 destroy();
00164 
00165             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00166         }
00167 
00168         virtual void destroy(void)
00169         {
00170             // IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS
00171             // BEFORE SHUTTING OGRE DOWN
00172             // Use setNull() before shutdown or make sure your pointer goes
00173             // out of scope before OGRE shuts down to avoid this.
00174             delete pRep;
00175             delete pUseCount;
00176             OGRE_DELETE_AUTO_SHARED_MUTEX
00177         }
00178     };
00179 
00180     template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b)
00181     {
00182         return a.get() == b.get();
00183     }
00184 
00185     template<class T, class U> inline bool operator!=(SharedPtr<T> const& a, SharedPtr<U> const& b)
00186     {
00187         return a.get() != b.get();
00188     }
00189 }
00190 
00191 
00192 
00193 #endif

Copyright © 2000-2005 by The OGRE Team
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.
Last modified Sun Jul 23 10:05:41 2006