source: GTP/trunk/App/Demos/Geom/OgreStuff/include/OgreSharedPtr.h @ 1812

Revision 1812, 5.9 KB checked in by gumbau, 18 years ago (diff)
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#ifndef __SharedPtr_H__
26#define __SharedPtr_H__
27
28#include "OgrePrerequisites.h"
29
30namespace Ogre {
31
32        /** Reference-counted shared pointer, used for objects where implicit destruction is
33        required.
34    @remarks
35        This is a standard shared pointer implementation which uses a reference
36        count to work out when to delete the object. OGRE does not use this class
37        very often, because it is usually more efficient to make the destruction
38        of objects more intentional (in blocks, say). However in some cases you
39        really cannot tell how many people are using an object, and this approach is
40        worthwhile (e.g. ControllerValue)
41        @par
42                If OGRE_THREAD_SUPPORT is defined to be 1, use of this class is thread-safe.
43    */
44    template<class T> class SharedPtr {
45        protected:
46                T* pRep;
47                unsigned int* pUseCount;
48        public:
49                OGRE_AUTO_SHARED_MUTEX // public to allow external locking
50                /** Constructor, does not initialise the SharedPtr.
51                        @remarks
52                                <b>Dangerous!</b> You have to call bind() before using the SharedPtr.
53                */
54                SharedPtr() : pRep(0), pUseCount(0)
55        {
56            OGRE_SET_AUTO_SHARED_MUTEX_NULL
57        }
58
59                explicit SharedPtr(T* rep) : pRep(rep), pUseCount(new unsigned int(1))
60                {
61            OGRE_SET_AUTO_SHARED_MUTEX_NULL
62                        OGRE_NEW_AUTO_SHARED_MUTEX
63                }
64                SharedPtr(const SharedPtr& r)
65            : pRep(0), pUseCount(0)
66                {
67                        // lock & copy other mutex pointer
68           
69            OGRE_SET_AUTO_SHARED_MUTEX_NULL
70            OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
71            {
72                            OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
73                            OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
74                            pRep = r.pRep;
75                            pUseCount = r.pUseCount;
76                            // Handle zero pointer gracefully to manage STL containers
77                            if(pUseCount)
78                            {
79                                    ++(*pUseCount);
80                            }
81            }
82                }
83                SharedPtr& operator=(const SharedPtr& r) {
84                        if (pRep == r.pRep)
85                                return *this;
86                        release();
87                        // lock & copy other mutex pointer
88            OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
89            {
90                            OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
91                            OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
92                            pRep = r.pRep;
93                            pUseCount = r.pUseCount;
94                            if (pUseCount)
95                            {
96                                    ++(*pUseCount);
97                            }
98            }
99                        return *this;
100                }
101                virtual ~SharedPtr() {
102            release();
103                }
104
105
106                inline T& operator*() const { assert(pRep); return *pRep; }
107                inline T* operator->() const { assert(pRep); return pRep; }
108                inline T* get() const { return pRep; }
109
110                /** Binds rep to the SharedPtr.
111                        @remarks
112                                Assumes that the SharedPtr is uninitialised!
113                */
114                void bind(T* rep) {
115                        assert(!pRep && !pUseCount);
116            OGRE_NEW_AUTO_SHARED_MUTEX
117                        OGRE_LOCK_AUTO_SHARED_MUTEX
118                        pUseCount = new unsigned int(1);
119                        pRep = rep;
120                }
121
122                inline bool unique() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount == 1; }
123                inline unsigned int useCount() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount; }
124                inline unsigned int* useCountPointer() const { return pUseCount; }
125
126                inline T* getPointer() const { return pRep; }
127
128                inline bool isNull(void) const { return pRep == 0; }
129
130        inline void setNull(void) {
131                        if (pRep)
132                        {
133                                // can't scope lock mutex before release incase deleted
134                                release();
135                                pRep = 0;
136                                pUseCount = 0;
137                        }
138        }
139
140    protected:
141
142        inline void release(void)
143        {
144                        bool destroyThis = false;
145
146            /* If the mutex is not initialized to a non-zero value, then
147               neither is pUseCount nor pRep.
148             */
149
150            OGRE_MUTEX_CONDITIONAL(OGRE_AUTO_MUTEX_NAME)
151                        {
152                                // lock own mutex in limited scope (must unlock before destroy)
153                                OGRE_LOCK_AUTO_SHARED_MUTEX
154                                if (pUseCount)
155                                {
156                                        if (--(*pUseCount) == 0)
157                                        {
158                                                destroyThis = true;
159                        }
160                                }
161            }
162                        if (destroyThis)
163                                destroy();
164
165            OGRE_SET_AUTO_SHARED_MUTEX_NULL
166        }
167
168        virtual void destroy(void)
169        {
170            // IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS
171            // BEFORE SHUTTING OGRE DOWN
172            // Use setNull() before shutdown or make sure your pointer goes
173            // out of scope before OGRE shuts down to avoid this.
174            delete pRep;
175            delete pUseCount;
176                        OGRE_DELETE_AUTO_SHARED_MUTEX
177        }
178        };
179
180        template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b)
181        {
182                return a.get() == b.get();
183        }
184
185        template<class T, class U> inline bool operator!=(SharedPtr<T> const& a, SharedPtr<U> const& b)
186        {
187                return a.get() != b.get();
188        }
189}
190
191
192
193#endif
Note: See TracBrowser for help on using the repository browser.