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-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 
00048     template<class T> class SharedPtr {
00049     protected:
00050         T* pRep;
00051         unsigned int* pUseCount;
00052     public:
00053         OGRE_AUTO_SHARED_MUTEX // public to allow external locking
00058         SharedPtr() : pRep(0), pUseCount(0)
00059         {
00060             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00061         }
00062 
00063         template< class Y>
00064         explicit SharedPtr(Y* rep) : pRep(rep), pUseCount(new unsigned int(1))
00065         {
00066             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00067             OGRE_NEW_AUTO_SHARED_MUTEX
00068         }
00069         SharedPtr(const SharedPtr& r)
00070             : pRep(0), pUseCount(0)
00071         {
00072             // lock & copy other mutex pointer
00073             
00074             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00075             OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
00076             {
00077                 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
00078                 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
00079                 pRep = r.pRep;
00080                 pUseCount = r.pUseCount; 
00081                 // Handle zero pointer gracefully to manage STL containers
00082                 if(pUseCount)
00083                 {
00084                     ++(*pUseCount); 
00085                 }
00086             }
00087         }
00088         SharedPtr& operator=(const SharedPtr& r) {
00089             if (pRep == r.pRep)
00090                 return *this;
00091             release();
00092             // lock & copy other mutex pointer
00093             OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
00094             {
00095                 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
00096                 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
00097                 pRep = r.pRep;
00098                 pUseCount = r.pUseCount;
00099                 if (pUseCount)
00100                 {
00101                     ++(*pUseCount);
00102                 }
00103             }
00104             else
00105             {
00106                 // RHS must be a null pointer
00107                 assert(r.isNull() && "RHS must be null if it has no mutex!");
00108                 setNull();
00109             }
00110             return *this;
00111         }
00112         
00113         template< class Y>
00114         SharedPtr(const SharedPtr<Y>& r)
00115             : pRep(0), pUseCount(0)
00116         {
00117             // lock & copy other mutex pointer
00118 
00119             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00120             OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
00121             {
00122                 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
00123                 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
00124                 pRep = r.getPointer();
00125                 pUseCount = r.useCountPointer();
00126                 // Handle zero pointer gracefully to manage STL containers
00127                 if(pUseCount)
00128                 {
00129                     ++(*pUseCount);
00130                 }
00131             }
00132         }
00133         template< class Y>
00134         SharedPtr& operator=(const SharedPtr<Y>& r) {
00135             if (pRep == r.pRep)
00136                 return *this;
00137             release();
00138             // lock & copy other mutex pointer
00139             OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
00140             {
00141                 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
00142                 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
00143                 pRep = r.getPointer();
00144                 pUseCount = r.useCountPointer();
00145                 if (pUseCount)
00146                 {
00147                     ++(*pUseCount);
00148                 }
00149             }
00150             return *this;
00151         }
00152         virtual ~SharedPtr() {
00153             release();
00154         }
00155 
00156 
00157         inline T& operator*() const { assert(pRep); return *pRep; }
00158         inline T* operator->() const { assert(pRep); return pRep; }
00159         inline T* get() const { return pRep; }
00160 
00165         void bind(T* rep) {
00166             assert(!pRep && !pUseCount);
00167             OGRE_NEW_AUTO_SHARED_MUTEX
00168             OGRE_LOCK_AUTO_SHARED_MUTEX
00169             pUseCount = new unsigned int(1);
00170             pRep = rep;
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 
00179         inline bool isNull(void) const { return pRep == 0; }
00180 
00181         inline void setNull(void) { 
00182             if (pRep)
00183             {
00184                 // can't scope lock mutex before release incase deleted
00185                 release();
00186                 pRep = 0;
00187                 pUseCount = 0;
00188             }
00189         }
00190 
00191     protected:
00192 
00193         inline void release(void)
00194         {
00195             bool destroyThis = false;
00196 
00197             /* If the mutex is not initialized to a non-zero value, then
00198                neither is pUseCount nor pRep.
00199              */
00200 
00201             OGRE_MUTEX_CONDITIONAL(OGRE_AUTO_MUTEX_NAME)
00202             {
00203                 // lock own mutex in limited scope (must unlock before destroy)
00204                 OGRE_LOCK_AUTO_SHARED_MUTEX
00205                 if (pUseCount)
00206                 {
00207                     if (--(*pUseCount) == 0) 
00208                     {
00209                         destroyThis = true;
00210                     }
00211                 }
00212             }
00213             if (destroyThis)
00214                 destroy();
00215 
00216             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00217         }
00218 
00219         virtual void destroy(void)
00220         {
00221             // IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS
00222             // BEFORE SHUTTING OGRE DOWN
00223             // Use setNull() before shutdown or make sure your pointer goes
00224             // out of scope before OGRE shuts down to avoid this.
00225             delete pRep;
00226             delete pUseCount;
00227             OGRE_DELETE_AUTO_SHARED_MUTEX
00228         }
00229     };
00230 
00231     template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b)
00232     {
00233         return a.get() == b.get();
00234     }
00235 
00236     template<class T, class U> inline bool operator!=(SharedPtr<T> const& a, SharedPtr<U> const& b)
00237     {
00238         return a.get() != b.get();
00239     }
00240 }
00241 
00242 
00243 
00244 #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 May 6 10:54:23 2007