OGRE  1.9.0
OgreSharedPtr.h
Go to the documentation of this file.
1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4  (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
6 
7 Copyright (c) 2000-2014 Torus Knot Software Ltd
8 
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15 
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 THE SOFTWARE.
26 -----------------------------------------------------------------------------
27 */
28 #ifndef __SharedPtr_H__
29 #define __SharedPtr_H__
30 
31 #include "OgrePrerequisites.h"
32 #include "OgreAtomicScalar.h"
33 
34 namespace Ogre {
44  {
53  };
54 
55  struct SharedPtrInfo {
56  inline SharedPtrInfo()
57  : useCount(1)
58  {}
59 
60  virtual ~SharedPtrInfo() {}
61 
63  };
64 
66  {
67  };
68 
69  template <class T>
71  {
72  T* mObject;
73  public:
74  inline SharedPtrInfoDelete(T* o) : mObject(o) {}
75 
77  {
79  }
80  };
81 
82  template <class T>
84  {
85  T* mObject;
86  public:
87  inline SharedPtrInfoDeleteT(T* o) : mObject(o) {}
88 
90  {
92  }
93  };
94 
95  template <class T>
97  {
98  T* mObject;
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 
133  T* pRep;
135 
136  SharedPtr(T* rep, SharedPtrInfo* info) : pRep(rep), pInfo(info)
137  {
138  }
139 
140  public:
145  SharedPtr() : pRep(0), pInfo(0)
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>
244  inline SharedPtr<Y> staticCast() const
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>
253  inline SharedPtr<Y> dynamicCast() const
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
SharedPtr(const SharedPtr< Y > &r)
void setUseCount(unsigned value)
void swap(SharedPtr< T > &other)
Use OGRE_DELETE to free the memory.
Definition: OgreSharedPtr.h:46
#define OGRE_DELETE
SharedPtr(T *rep, SharedPtrInfo *info)
SharedPtr & operator=(const SharedPtr< Y > &r)
Use OGRE_FREE to free (only MEMCATEGORY_GENERAL supported)
Definition: OgreSharedPtr.h:50
bool unique() const
virtual ~SharedPtrInfo()
Definition: OgreSharedPtr.h:60
AtomicScalar< unsigned > useCount
Definition: OgreSharedPtr.h:62
bool isNull(void) const
void setNull(void)
SharedPtr & operator=(const SharedPtr &r)
SharedPtr(const SharedPtr &r)
T & operator *() const
Don`t free resource at all, lifetime controlled externally.
Definition: OgreSharedPtr.h:52
#define OGRE_FREE(ptr, category)
Free the memory allocated with OGRE_MALLOC or OGRE_ALLOC_T. Category is required to be restated to en...
bool operator!=(STLAllocator< T, P > const &, STLAllocator< T2, P > const &)
determine equality, can memory from another allocator be released by this allocator,...
#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...
T * operator->() const
void release(void)
unsigned int useCount() const
SharedPtr()
Constructor, does not initialise the SharedPtr.
SharedPtr< Y > dynamicCast() const
#define OGRE_NEW_T(T, category)
Allocate space for one primitive type, external type or non-virtual type with constructor parameters.
void swap(Ogre::SmallVectorImpl< T > &LHS, Ogre::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
void bind(T *rep, SharedPtrFreeMethod inFreeMethod=SPFM_DELETE)
Binds rep to the SharedPtr.
T * get() const
void destroy(void)
IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS BEFORE SHUTTING OGRE DOWN Use setNull() befor...
SharedPtrFreeMethod
The method to use to free memory on destruction.
Definition: OgreSharedPtr.h:43
Reference-counted shared pointer, used for objects where implicit destruction is required.
SharedPtr(Y *rep, SharedPtrFreeMethod inFreeMethod=SPFM_DELETE)
Constructor.
T * getPointer() const
bool operator==(STLAllocator< T, P > const &, STLAllocator< T2, P > const &)
determine equality, can memory from another allocator be released by this allocator,...
SharedPtrInfo * pInfo
SharedPtr< Y > staticCast() const
Use OGRE_DELETE_T to free (only MEMCATEGORY_GENERAL supported)
Definition: OgreSharedPtr.h:48
static SharedPtrInfo * createInfoForMethod(T *rep, SharedPtrFreeMethod method)
bool operator<(SharedPtr< T > const &a, SharedPtr< U > const &b)