Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogre_src_v1-9-0/OgreMain/include/OgreSharedPtr.h @ 148

Last change on this file since 148 was 148, checked in by patricwi, 6 years ago

Added new dependencies for ogre1.9 and cegui0.8

File size: 9.2 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-2013 Torus Knot Software Ltd
8
9Permission is hereby granted, free of charge, to any person obtaining a copy
10of this software and associated documentation files (the "Software"), to deal
11in the Software without restriction, including without limitation the rights
12to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13copies of the Software, and to permit persons to whom the Software is
14furnished to do so, subject to the following conditions:
15
16The above copyright notice and this permission notice shall be included in
17all copies or substantial portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25THE SOFTWARE.
26-----------------------------------------------------------------------------
27*/
28#ifndef __SharedPtr_H__
29#define __SharedPtr_H__
30
31#include "OgrePrerequisites.h"
32#include "OgreAtomicScalar.h"
33
34namespace Ogre {
35        /** \addtogroup Core
36        *  @{
37        */
38        /** \addtogroup General
39        *  @{
40        */
41
42        /// The method to use to free memory on destruction
43        enum SharedPtrFreeMethod
44        {
45                /// Use OGRE_DELETE to free the memory
46                SPFM_DELETE,
47                /// Use OGRE_DELETE_T to free (only MEMCATEGORY_GENERAL supported)
48                SPFM_DELETE_T,
49                /// Use OGRE_FREE to free (only MEMCATEGORY_GENERAL supported)
50                SPFM_FREE
51        };
52
53    struct SharedPtrInfo {
54        inline SharedPtrInfo() 
55            : useCount(1)
56        {}
57
58        virtual ~SharedPtrInfo() {}
59
60        AtomicScalar<unsigned>  useCount;
61    };
62
63        template <class T>
64        class SharedPtrInfoDelete : public SharedPtrInfo
65        {
66        T* mObject;
67    public:
68        inline SharedPtrInfoDelete(T* o) : mObject(o) {}
69
70                virtual ~SharedPtrInfoDelete()
71                {
72                        OGRE_DELETE mObject;
73                }
74        };
75
76        template <class T>
77        class SharedPtrInfoDeleteT : public SharedPtrInfo
78        {
79        T* mObject;
80    public:
81        inline SharedPtrInfoDeleteT(T* o) : mObject(o) {}
82
83                virtual ~SharedPtrInfoDeleteT()
84                {
85                        OGRE_DELETE_T(mObject, T, MEMCATEGORY_GENERAL);
86                }
87        };
88
89        template <class T>
90        class SharedPtrInfoFree : public SharedPtrInfo
91        {
92        T* mObject;
93    public:
94        inline SharedPtrInfoFree(T* o) : mObject(o) {}       
95
96                virtual ~SharedPtrInfoFree()
97                {
98                        OGRE_FREE(mObject, MEMCATEGORY_GENERAL);
99                }
100        };
101
102
103        /** Reference-counted shared pointer, used for objects where implicit destruction is
104        required.
105    @remarks
106        This is a standard shared pointer implementation which uses a reference
107        count to work out when to delete the object.
108        @par
109                If OGRE_THREAD_SUPPORT is defined to be 1, use of this class is thread-safe.
110    */
111        template<class T> class SharedPtr
112        {
113        template<typename Y> friend class SharedPtr;
114        protected:
115        /* DO NOT ADD MEMBERS TO THIS CLASS!
116         *
117         * The average Ogre application has *thousands* of them. Every extra
118         * member causes extra memory use in general, and causes extra padding
119         * to be added to a multitude of structures.
120         *
121         * Everything you need to do can be acomplished by creatively working
122         * with the SharedPtrInfo object.
123         *
124         * There is no reason for this object to ever have more than two members.
125         */
126
127                T*             pRep;
128        SharedPtrInfo* pInfo;
129
130        SharedPtr(T* rep, SharedPtrInfo* info) : pRep(rep), pInfo(info)
131                {
132                }
133
134        public:
135                /** Constructor, does not initialise the SharedPtr.
136                        @remarks
137                                <b>Dangerous!</b> You have to call bind() before using the SharedPtr.
138                */
139                SharedPtr() : pRep(0), pInfo(0)
140        {}
141
142    private:
143        static SharedPtrInfo* createInfoForMethod(T* rep, SharedPtrFreeMethod method)
144        {
145            switch(method) {
146                case SPFM_DELETE:   return OGRE_NEW_T(SharedPtrInfoDelete<T>,  MEMCATEGORY_GENERAL) (rep);
147                case SPFM_DELETE_T: return OGRE_NEW_T(SharedPtrInfoDeleteT<T>, MEMCATEGORY_GENERAL) (rep);
148                case SPFM_FREE:     return OGRE_NEW_T(SharedPtrInfoFree<T>,    MEMCATEGORY_GENERAL) (rep);
149            }
150            assert(!"Bad method");
151            return 0;
152        }
153    public:
154
155                /** Constructor.
156                @param rep The pointer to take ownership of
157                @param inFreeMethod The mechanism to use to free the pointer
158                */
159        template< class Y>
160                explicit SharedPtr(Y* rep, SharedPtrFreeMethod inFreeMethod = SPFM_DELETE) 
161            : pRep(rep)
162            , pInfo(rep ? createInfoForMethod(rep, inFreeMethod) : 0)
163                {
164                }
165
166                SharedPtr(const SharedPtr& r)
167            : pRep(r.pRep)
168            , pInfo(r.pInfo)
169                {
170            if (pRep) 
171            {
172                ++pInfo->useCount;
173            }
174                }
175
176                SharedPtr& operator=(const SharedPtr& r) {
177                        if (pRep == r.pRep)
178            {
179                assert(pInfo == r.pInfo);
180                                return *this;
181            }
182                        // Swap current data into a local copy
183                        // this ensures we deal with rhs and this being dependent
184                        SharedPtr<T> tmp(r);
185                        swap(tmp);
186                        return *this;
187                }
188               
189                /* For C++11 compilers, use enable_if to only expose functions when viable
190         *
191         * MSVC 2012 and earlier only claim conformance to C++98. This is fortunate,
192         * because they don't support default template parameters
193         */
194#if __cplusplus >= 201103L
195        template<class Y,
196            class = typename std::enable_if<std::is_convertible<Y*, T*>::value>::type>
197#else
198        template<class Y>
199#endif
200        SharedPtr(const SharedPtr<Y>& r)
201            : pRep(r.getPointer())
202            , pInfo(r.pInfo)
203                {
204            if (pRep) 
205            {
206                ++pInfo->useCount;
207            }
208        }
209
210               
211#if __cplusplus >= 201103L
212        template<class Y,
213                 class = typename std::enable_if<std::is_assignable<T*, Y*>::value>::type>
214#else
215        template<class Y>
216#endif
217        SharedPtr& operator=(const SharedPtr<Y>& r)
218        {
219                        if (pRep == r.pRep)
220                                return *this;
221                        // Swap current data into a local copy
222                        // this ensures we deal with rhs and this being dependent
223                        SharedPtr<T> tmp(r);
224                        swap(tmp);
225                        return *this;
226                }
227
228                ~SharedPtr() {
229            release();
230                }
231
232
233        template<typename Y>
234        inline SharedPtr<Y> staticCast() const
235        {
236            if(pRep) {
237                ++pInfo->useCount;
238                                return SharedPtr<Y>(static_cast<Y*>(pRep), pInfo);
239            } else return SharedPtr<Y>();
240        }
241
242        template<typename Y>
243        inline SharedPtr<Y> dynamicCast() const
244        {
245            if(pRep) {
246                Y* rep = dynamic_cast<Y*>(pRep);
247                ++pInfo->useCount;
248                                return SharedPtr<Y>(rep, pInfo);
249            } else return SharedPtr<Y>();
250        }
251
252                inline T& operator*() const { assert(pRep); return *pRep; }
253                inline T* operator->() const { assert(pRep); return pRep; }
254                inline T* get() const { return pRep; }
255
256                /** Binds rep to the SharedPtr.
257                        @remarks
258                                Assumes that the SharedPtr is uninitialised!
259
260            @warning
261                The object must not be bound into a SharedPtr elsewhere
262                */
263                void bind(T* rep, SharedPtrFreeMethod inFreeMethod = SPFM_DELETE) {
264                        assert(!pRep && !pInfo);
265                        pInfo = createInfoForMethod(rep, inFreeMethod);
266                        pRep = rep;
267                }
268
269                inline bool unique() const { assert(pInfo && pInfo->useCount.get()); return pInfo->useCount.get() == 1; }
270                inline unsigned int useCount() const { assert(pInfo && pInfo->useCount.get()); return pInfo->useCount.get(); }
271        inline void setUseCount(unsigned value) { assert(pInfo); pInfo->useCount = value; }
272
273                inline T* getPointer() const { return pRep; }
274
275                inline bool isNull(void) const { return pRep == 0; }
276
277        inline void setNull(void) { 
278                        if (pRep)
279                        {
280                                release();
281                        }
282        }
283
284    protected:
285
286        inline void release(void)
287        {
288            if (pRep)
289            {
290                assert(pInfo);
291                if(--pInfo->useCount == 0)
292                    destroy();
293            }
294
295            pRep = 0;
296            pInfo = 0;
297        }
298
299        /** IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS
300         BEFORE SHUTTING OGRE DOWN
301         Use setNull() before shutdown or make sure your pointer goes
302         out of scope before OGRE shuts down to avoid this. */
303        inline void destroy(void)
304        {
305            assert(pRep && pInfo);
306            OGRE_DELETE_T(pInfo, SharedPtrInfo, MEMCATEGORY_GENERAL);
307        }
308
309                inline void swap(SharedPtr<T> &other) 
310                {
311                        std::swap(pRep, other.pRep);
312                        std::swap(pInfo, other.pInfo);
313                }
314        };
315
316        template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b)
317        {
318                return a.get() == b.get();
319        }
320
321        template<class T, class U> inline bool operator!=(SharedPtr<T> const& a, SharedPtr<U> const& b)
322        {
323                return a.get() != b.get();
324        }
325
326        template<class T, class U> inline bool operator<(SharedPtr<T> const& a, SharedPtr<U> const& b)
327        {
328                return std::less<const void*>()(a.get(), b.get());
329        }
330        /** @} */
331        /** @} */
332}
333
334
335
336#endif
Note: See TracBrowser for help on using the repository browser.