OGRE  1.9.0
OgreSharedPtr.h
Go to the documentation of this file.
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-2014 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 {
44 {
53 };
54
56 inline SharedPtrInfo()
57 : useCount(1)
58 {}
59
60 virtual ~SharedPtrInfo() {}
61
63 };
64
66 {
67 };
68
69 template <class T>
71 {
73 public:
74 inline SharedPtrInfoDelete(T* o) : mObject(o) {}
75
77 {
79 }
80 };
81
82 template <class T>
84 {
86 public:
87 inline SharedPtrInfoDeleteT(T* o) : mObject(o) {}
88
90 {
92 }
93 };
94
95 template <class T>
97 {
99 public:
100 inline SharedPtrInfoFree(T* o) : mObject(o) {}
101
103 {
105 }
106 };
107
108
117 template<class T> class SharedPtr
118 {
119 template<typename Y> friend class SharedPtr;
120 protected:
121 /* DO NOT ADD MEMBERS TO THIS CLASS!
122 *
123 * The average Ogre application has *thousands* of them. Every extra
124 * member causes extra memory use in general, and causes extra padding
125 * to be added to a multitude of structures.
126 *
127 * Everything you need to do can be acomplished by creatively working
128 * with the SharedPtrInfo object.
129 *
130 * There is no reason for this object to ever have more than two members.
131 */
132
135
136 SharedPtr(T* rep, SharedPtrInfo* info) : pRep(rep), pInfo(info)
137 {
138 }
139
140 public:
146 {}
147
148 private:
150 {
151 switch(method) {
156 }
157 assert(!"Bad method");
158 return 0;
159 }
160 public:
161
166 template< class Y>
167 explicit SharedPtr(Y* rep, SharedPtrFreeMethod inFreeMethod = SPFM_DELETE)
168 : pRep(rep)
169 , pInfo(rep ? createInfoForMethod(rep, inFreeMethod) : 0)
170 {
171 }
172
174 : pRep(r.pRep)
175 , pInfo(r.pInfo)
176 {
177 if (pRep)
178 {
179 ++pInfo->useCount;
180 }
181 }
182
184 // One resource could have several non-controlling control blocks but only one controlling.
185 assert(pRep != r.pRep || pInfo == r.pInfo || dynamic_cast<SharedPtrInfoNone*>(pInfo) || dynamic_cast<SharedPtrInfoNone*>(r.pInfo));
186 if(pInfo == r.pInfo)
187 return *this;
188
189 // Swap current data into a local copy
190 // this ensures we deal with rhs and this being dependent
191 SharedPtr<T> tmp(r);
192 swap(tmp);
193 return *this;
194 }
195
196 /* For C++11 compilers, use enable_if to only expose functions when viable
197 *
198 * MSVC 2012 and earlier only claim conformance to C++98. This is fortunate,
199 * because they don't support default template parameters
200 */
201#if __cplusplus >= 201103L
202 template<class Y,
203 class = typename std::enable_if<std::is_convertible<Y*, T*>::value>::type>
204#else
205 template<class Y>
206#endif
208 : pRep(r.getPointer())
209 , pInfo(r.pInfo)
210 {
211 if (pRep)
212 {
213 ++pInfo->useCount;
214 }
215 }
216
217
218#if __cplusplus >= 201103L
219 template<class Y,
220 class = typename std::enable_if<std::is_assignable<T*, Y*>::value>::type>
221#else
222 template<class Y>
223#endif
225 {
226 // One resource could have several non-controlling control blocks but only one controlling.
227 assert(pRep != r.pRep || pInfo == r.pInfo|| dynamic_cast<SharedPtrInfoNone*>(pInfo) || dynamic_cast<SharedPtrInfoNone*>(r.pInfo));
228 if(pInfo == r.pInfo)
229 return *this;
230
231 // Swap current data into a local copy
232 // this ensures we deal with rhs and this being dependent
233 SharedPtr<T> tmp(r);
234 swap(tmp);
235 return *this;
236 }
237
239 release();
240 }
241
242
243 template<typename Y>
245 {
246 if(pRep) {
247 ++pInfo->useCount;
248 return SharedPtr<Y>(static_cast<Y*>(pRep), pInfo);
249 } else return SharedPtr<Y>();
250 }
251
252 template<typename Y>
254 {
255 Y* rep = dynamic_cast<Y*>(pRep);
256 if(rep) {
257 ++pInfo->useCount;
258 return SharedPtr<Y>(rep, pInfo);
259 } else return SharedPtr<Y>();
260 }
261
262 inline T& operator*() const { assert(pRep); return *pRep; }
263 inline T* operator->() const { assert(pRep); return pRep; }
264 inline T* get() const { return pRep; }
265
273 void bind(T* rep, SharedPtrFreeMethod inFreeMethod = SPFM_DELETE) {
274 assert(!pRep && !pInfo);
275 pInfo = createInfoForMethod(rep, inFreeMethod);
276 pRep = rep;
277 }
278
279 inline bool unique() const { assert(pInfo && pInfo->useCount.get()); return pInfo->useCount.get() == 1; }
280 inline unsigned int useCount() const { assert(pInfo && pInfo->useCount.get()); return pInfo->useCount.get(); }
281 inline void setUseCount(unsigned value) { assert(pInfo); pInfo->useCount = value; }
282
283 inline T* getPointer() const { return pRep; }
284
285 inline bool isNull(void) const { return pRep == 0; }
286
287 inline void setNull(void) {
288 if (pRep)
289 {
290 release();
291 }
292 }
293
294 protected:
295
296 inline void release(void)
297 {
298 if (pRep)
299 {
300 assert(pInfo);
301 if(--pInfo->useCount == 0)
302 destroy();
303 }
304
305 pRep = 0;
306 pInfo = 0;
307 }
308
313 inline void destroy(void)
314 {
315 assert(pRep && pInfo);
317 }
318
319 inline void swap(SharedPtr<T> &other)
320 {
321 std::swap(pRep, other.pRep);
322 std::swap(pInfo, other.pInfo);
323 }
324 };
325
326 template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b)
327 {
328 return a.get() == b.get();
329 }
330
331 template<class T, class U> inline bool operator!=(SharedPtr<T> const& a, SharedPtr<U> const& b)
332 {
333 return a.get() != b.get();
334 }
335
336 template<class T, class U> inline bool operator<(SharedPtr<T> const& a, SharedPtr<U> const& b)
337 {
338 return std::less<const void*>()(a.get(), b.get());
339 }
342}
343
344
345
346#endif
Reference-counted shared pointer, used for objects where implicit destruction is required.
bool unique() const
SharedPtr & operator=(const SharedPtr< Y > &r)
T & operator*() const
SharedPtr(T *rep, SharedPtrInfo *info)
void setUseCount(unsigned value)
void destroy(void)
IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS BEFORE SHUTTING OGRE DOWN Use setNull() befor...
SharedPtrInfo * pInfo
SharedPtr()
Constructor, does not initialise the SharedPtr.
static SharedPtrInfo * createInfoForMethod(T *rep, SharedPtrFreeMethod method)
void swap(SharedPtr< T > &other)
unsigned int useCount() const
SharedPtr(Y *rep, SharedPtrFreeMethod inFreeMethod=SPFM_DELETE)
Constructor.
bool isNull(void) const
SharedPtr & operator=(const SharedPtr &r)
void release(void)
SharedPtr(const SharedPtr &r)
T * operator->() const
SharedPtr< Y > dynamicCast() const
void bind(T *rep, SharedPtrFreeMethod inFreeMethod=SPFM_DELETE)
Binds rep to the SharedPtr.
SharedPtr(const SharedPtr< Y > &r)
T * getPointer() const
T * get() const
void setNull(void)
SharedPtr< Y > staticCast() const
SharedPtrFreeMethod
The method to use to free memory on destruction.
Definition: OgreSharedPtr.h:44
bool operator<(SharedPtr< T > const &a, SharedPtr< U > const &b)
@ SPFM_NONE
Don`t free resource at all, lifetime controlled externally.
Definition: OgreSharedPtr.h:52
@ SPFM_DELETE_T
Use OGRE_DELETE_T to free (only MEMCATEGORY_GENERAL supported)
Definition: OgreSharedPtr.h:48
@ SPFM_DELETE
Use OGRE_DELETE to free the memory.
Definition: OgreSharedPtr.h:46
@ SPFM_FREE
Use OGRE_FREE to free (only MEMCATEGORY_GENERAL supported)
Definition: OgreSharedPtr.h:50
#define OGRE_DELETE_T(ptr, T, category)
Free the memory allocated with OGRE_NEW_T. Category is required to be restated to ensure the matching...
bool operator!=(STLAllocator< T, P > const &, STLAllocator< T2, P > const &)
determine equality, can memory from another allocator be released by this allocator,...
#define OGRE_NEW_T(T, category)
Allocate space for one primitive type, external type or non-virtual type with constructor parameters.
bool operator==(STLAllocator< T, P > const &, STLAllocator< T2, P > const &)
determine equality, can memory from another allocator be released by this allocator,...
#define OGRE_FREE(ptr, category)
Free the memory allocated with OGRE_MALLOC or OGRE_ALLOC_T. Category is required to be restated to en...
#define OGRE_DELETE
@ MEMCATEGORY_GENERAL
General purpose.
void swap(Ogre::SmallVectorImpl< T > &LHS, Ogre::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
AtomicScalar< unsigned > useCount
Definition: OgreSharedPtr.h:62
virtual ~SharedPtrInfo()
Definition: OgreSharedPtr.h:60