Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/include/OgreSharedPtr.h @ 5

Last change on this file since 5 was 5, checked in by anonymous, 17 years ago

=hoffentlich gehts jetzt

File size: 6.7 KB
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-2006 Torus Knot Software Ltd
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
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#ifndef __SharedPtr_H__
30#define __SharedPtr_H__
31
32#include "OgrePrerequisites.h"
33
34namespace Ogre {
35
36        /** Reference-counted shared pointer, used for objects where implicit destruction is
37        required.
38    @remarks
39        This is a standard shared pointer implementation which uses a reference
40        count to work out when to delete the object. OGRE does not use this class
41        very often, because it is usually more efficient to make the destruction
42        of objects more intentional (in blocks, say). However in some cases you
43        really cannot tell how many people are using an object, and this approach is
44        worthwhile (e.g. ControllerValue)
45        @par
46                If OGRE_THREAD_SUPPORT is defined to be 1, use of this class is thread-safe.
47    */
48    template<class T> class SharedPtr {
49        protected:
50                T* pRep;
51                unsigned int* pUseCount;
52        public:
53                OGRE_AUTO_SHARED_MUTEX // public to allow external locking
54                /** Constructor, does not initialise the SharedPtr.
55                        @remarks
56                                <b>Dangerous!</b> You have to call bind() before using the SharedPtr.
57                */
58                SharedPtr() : pRep(0), pUseCount(0)
59        {
60            OGRE_SET_AUTO_SHARED_MUTEX_NULL
61        }
62
63        template< class Y>
64                explicit SharedPtr(Y* rep) : pRep(rep), pUseCount(new unsigned int(1))
65                {
66            OGRE_SET_AUTO_SHARED_MUTEX_NULL
67                        OGRE_NEW_AUTO_SHARED_MUTEX
68                }
69                SharedPtr(const SharedPtr& r)
70            : pRep(0), pUseCount(0)
71                {
72                        // lock & copy other mutex pointer
73           
74            OGRE_SET_AUTO_SHARED_MUTEX_NULL
75            OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
76            {
77                            OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
78                            OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
79                            pRep = r.pRep;
80                            pUseCount = r.pUseCount; 
81                            // Handle zero pointer gracefully to manage STL containers
82                            if(pUseCount)
83                            {
84                                    ++(*pUseCount); 
85                            }
86            }
87                }
88                SharedPtr& operator=(const SharedPtr& r) {
89                        if (pRep == r.pRep)
90                                return *this;
91                        // Swap current data into a local copy
92                        // this ensures we deal with rhs and this being dependent
93                        SharedPtr<T> tmp(r);
94                        swap(tmp);
95                        return *this;
96                }
97               
98                template< class Y>
99                SharedPtr(const SharedPtr<Y>& r)
100            : pRep(0), pUseCount(0)
101                {
102                        // lock & copy other mutex pointer
103
104            OGRE_SET_AUTO_SHARED_MUTEX_NULL
105            OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
106            {
107                            OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
108                            OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
109                            pRep = r.getPointer();
110                            pUseCount = r.useCountPointer();
111                            // Handle zero pointer gracefully to manage STL containers
112                            if(pUseCount)
113                            {
114                                    ++(*pUseCount);
115                            }
116            }
117                }
118                template< class Y>
119                SharedPtr& operator=(const SharedPtr<Y>& r) {
120                        if (pRep == r.pRep)
121                                return *this;
122                        // Swap current data into a local copy
123                        // this ensures we deal with rhs and this being dependent
124                        SharedPtr<T> tmp(r);
125                        swap(tmp);
126                        return *this;
127                }
128                virtual ~SharedPtr() {
129            release();
130                }
131
132
133                inline T& operator*() const { assert(pRep); return *pRep; }
134                inline T* operator->() const { assert(pRep); return pRep; }
135                inline T* get() const { return pRep; }
136
137                /** Binds rep to the SharedPtr.
138                        @remarks
139                                Assumes that the SharedPtr is uninitialised!
140                */
141                void bind(T* rep) {
142                        assert(!pRep && !pUseCount);
143            OGRE_NEW_AUTO_SHARED_MUTEX
144                        OGRE_LOCK_AUTO_SHARED_MUTEX
145                        pUseCount = new unsigned int(1);
146                        pRep = rep;
147                }
148
149                inline bool unique() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount == 1; }
150                inline unsigned int useCount() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount; }
151                inline unsigned int* useCountPointer() const { return pUseCount; }
152
153                inline T* getPointer() const { return pRep; }
154
155                inline bool isNull(void) const { return pRep == 0; }
156
157        inline void setNull(void) { 
158                        if (pRep)
159                        {
160                                // can't scope lock mutex before release incase deleted
161                                release();
162                                pRep = 0;
163                                pUseCount = 0;
164                        }
165        }
166
167    protected:
168
169        inline void release(void)
170        {
171                        bool destroyThis = false;
172
173            /* If the mutex is not initialized to a non-zero value, then
174               neither is pUseCount nor pRep.
175             */
176
177            OGRE_MUTEX_CONDITIONAL(OGRE_AUTO_MUTEX_NAME)
178                        {
179                                // lock own mutex in limited scope (must unlock before destroy)
180                                OGRE_LOCK_AUTO_SHARED_MUTEX
181                                if (pUseCount)
182                                {
183                                        if (--(*pUseCount) == 0) 
184                                        {
185                                                destroyThis = true;
186                        }
187                                }
188            }
189                        if (destroyThis)
190                                destroy();
191
192            OGRE_SET_AUTO_SHARED_MUTEX_NULL
193        }
194
195        virtual void destroy(void)
196        {
197            // IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS
198            // BEFORE SHUTTING OGRE DOWN
199            // Use setNull() before shutdown or make sure your pointer goes
200            // out of scope before OGRE shuts down to avoid this.
201            delete pRep;
202            delete pUseCount;
203                        OGRE_DELETE_AUTO_SHARED_MUTEX
204        }
205
206                virtual void swap(SharedPtr<T> &other) 
207                {
208                        std::swap(pRep, other.pRep);
209                        std::swap(pUseCount, other.pUseCount);
210#if OGRE_THREAD_SUPPORT
211                        std::swap(OGRE_AUTO_MUTEX_NAME, other.OGRE_AUTO_MUTEX_NAME);
212#endif
213                }
214        };
215
216        template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b)
217        {
218                return a.get() == b.get();
219        }
220
221        template<class T, class U> inline bool operator!=(SharedPtr<T> const& a, SharedPtr<U> const& b)
222        {
223                return a.get() != b.get();
224        }
225}
226
227
228
229#endif
Note: See TracBrowser for help on using the repository browser.