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 
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         template< class Y>
00060         explicit SharedPtr(Y* rep) : pRep(rep), pUseCount(new unsigned int(1))
00061         {
00062             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00063             OGRE_NEW_AUTO_SHARED_MUTEX
00064         }
00065         SharedPtr(const SharedPtr& r)
00066             : pRep(0), pUseCount(0)
00067         {
00068             // lock & copy other mutex pointer
00069             
00070             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00071             OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
00072             {
00073                 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
00074                 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
00075                 pRep = r.pRep;
00076                 pUseCount = r.pUseCount; 
00077                 // Handle zero pointer gracefully to manage STL containers
00078                 if(pUseCount)
00079                 {
00080                     ++(*pUseCount); 
00081                 }
00082             }
00083         }
00084         SharedPtr& operator=(const SharedPtr& r) {
00085             if (pRep == r.pRep)
00086                 return *this;
00087             // Swap current data into a local copy
00088             // this ensures we deal with rhs and this being dependent
00089             SharedPtr<T> tmp(r);
00090             swap(tmp);
00091             return *this;
00092         }
00093         
00094         template< class Y>
00095         SharedPtr(const SharedPtr<Y>& r)
00096             : pRep(0), pUseCount(0)
00097         {
00098             // lock & copy other mutex pointer
00099 
00100             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00101             OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
00102             {
00103                 OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
00104                 OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
00105                 pRep = r.getPointer();
00106                 pUseCount = r.useCountPointer();
00107                 // Handle zero pointer gracefully to manage STL containers
00108                 if(pUseCount)
00109                 {
00110                     ++(*pUseCount);
00111                 }
00112             }
00113         }
00114         template< class Y>
00115         SharedPtr& operator=(const SharedPtr<Y>& r) {
00116             if (pRep == r.pRep)
00117                 return *this;
00118             // Swap current data into a local copy
00119             // this ensures we deal with rhs and this being dependent
00120             SharedPtr<T> tmp(r);
00121             swap(tmp);
00122             return *this;
00123         }
00124         virtual ~SharedPtr() {
00125             release();
00126         }
00127 
00128 
00129         inline T& operator*() const { assert(pRep); return *pRep; }
00130         inline T* operator->() const { assert(pRep); return pRep; }
00131         inline T* get() const { return pRep; }
00132 
00137         void bind(T* rep) {
00138             assert(!pRep && !pUseCount);
00139             OGRE_NEW_AUTO_SHARED_MUTEX
00140             OGRE_LOCK_AUTO_SHARED_MUTEX
00141             pUseCount = new unsigned int(1);
00142             pRep = rep;
00143         }
00144 
00145         inline bool unique() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount == 1; }
00146         inline unsigned int useCount() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount; }
00147         inline unsigned int* useCountPointer() const { return pUseCount; }
00148 
00149         inline T* getPointer() const { return pRep; }
00150 
00151         inline bool isNull(void) const { return pRep == 0; }
00152 
00153         inline void setNull(void) { 
00154             if (pRep)
00155             {
00156                 // can't scope lock mutex before release incase deleted
00157                 release();
00158                 pRep = 0;
00159                 pUseCount = 0;
00160             }
00161         }
00162 
00163     protected:
00164 
00165         inline void release(void)
00166         {
00167             bool destroyThis = false;
00168 
00169             /* If the mutex is not initialized to a non-zero value, then
00170                neither is pUseCount nor pRep.
00171              */
00172 
00173             OGRE_MUTEX_CONDITIONAL(OGRE_AUTO_MUTEX_NAME)
00174             {
00175                 // lock own mutex in limited scope (must unlock before destroy)
00176                 OGRE_LOCK_AUTO_SHARED_MUTEX
00177                 if (pUseCount)
00178                 {
00179                     if (--(*pUseCount) == 0) 
00180                     {
00181                         destroyThis = true;
00182                     }
00183                 }
00184             }
00185             if (destroyThis)
00186                 destroy();
00187 
00188             OGRE_SET_AUTO_SHARED_MUTEX_NULL
00189         }
00190 
00191         virtual void destroy(void)
00192         {
00193             // IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS
00194             // BEFORE SHUTTING OGRE DOWN
00195             // Use setNull() before shutdown or make sure your pointer goes
00196             // out of scope before OGRE shuts down to avoid this.
00197             delete pRep;
00198             delete pUseCount;
00199             OGRE_DELETE_AUTO_SHARED_MUTEX
00200         }
00201 
00202         virtual void swap(SharedPtr<T> &other) 
00203         {
00204             std::swap(pRep, other.pRep);
00205             std::swap(pUseCount, other.pUseCount);
00206 #if OGRE_THREAD_SUPPORT
00207             std::swap(OGRE_AUTO_MUTEX_NAME, other.OGRE_AUTO_MUTEX_NAME);
00208 #endif
00209         }
00210     };
00211 
00212     template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b)
00213     {
00214         return a.get() == b.get();
00215     }
00216 
00217     template<class T, class U> inline bool operator!=(SharedPtr<T> const& a, SharedPtr<U> const& b)
00218     {
00219         return a.get() != b.get();
00220     }
00221 }
00222 
00223 
00224 
00225 #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 Sat May 10 16:25:03 2008