OGRE  1.7
Object-Oriented Graphics Rendering Engine
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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-2011 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 
33 namespace Ogre {
43  {
50  };
51 
60  template<class T> class SharedPtr
61  {
62  protected:
63  T* pRep;
64  unsigned int* pUseCount;
65  SharedPtrFreeMethod useFreeMethod; // if we should use OGRE_FREE instead of OGRE_DELETE
66  public:
67  OGRE_AUTO_SHARED_MUTEX // public to allow external locking
73  {
75  }
76 
81  template< class Y>
82  explicit SharedPtr(Y* rep, SharedPtrFreeMethod inFreeMethod = SPFM_DELETE)
83  : pRep(rep)
84  , pUseCount(rep ? OGRE_NEW_T(unsigned int, MEMCATEGORY_GENERAL)(1) : 0)
85  , useFreeMethod(inFreeMethod)
86  {
88  if (rep)
89  {
91  }
92  }
93  SharedPtr(const SharedPtr& r)
95  {
96  // lock & copy other mutex pointer
97 
99  OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
100  {
101  OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
102  OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
103  pRep = r.pRep;
104  pUseCount = r.pUseCount;
106  // Handle zero pointer gracefully to manage STL containers
107  if(pUseCount)
108  {
109  ++(*pUseCount);
110  }
111  }
112  }
114  if (pRep == r.pRep)
115  return *this;
116  // Swap current data into a local copy
117  // this ensures we deal with rhs and this being dependent
118  SharedPtr<T> tmp(r);
119  swap(tmp);
120  return *this;
121  }
122 
123  template< class Y>
126  {
127  // lock & copy other mutex pointer
128 
130  OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
131  {
132  OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
133  OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
134  pRep = r.getPointer();
137  // Handle zero pointer gracefully to manage STL containers
138  if(pUseCount)
139  {
140  ++(*pUseCount);
141  }
142  }
143  }
144  template< class Y>
146  if (pRep == r.getPointer())
147  return *this;
148  // Swap current data into a local copy
149  // this ensures we deal with rhs and this being dependent
150  SharedPtr<T> tmp(r);
151  swap(tmp);
152  return *this;
153  }
154  virtual ~SharedPtr() {
155  release();
156  }
157 
158 
159  inline T& operator*() const { assert(pRep); return *pRep; }
160  inline T* operator->() const { assert(pRep); return pRep; }
161  inline T* get() const { return pRep; }
162 
167  void bind(T* rep, SharedPtrFreeMethod inFreeMethod = SPFM_DELETE) {
168  assert(!pRep && !pUseCount);
171  pUseCount = OGRE_NEW_T(unsigned int, MEMCATEGORY_GENERAL)(1);
172  pRep = rep;
173  useFreeMethod = inFreeMethod;
174  }
175 
176  inline bool unique() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount == 1; }
177  inline unsigned int useCount() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount; }
178  inline unsigned int* useCountPointer() const { return pUseCount; }
179 
180  inline T* getPointer() const { return pRep; }
181  inline SharedPtrFreeMethod freeMethod() const { return useFreeMethod; }
182 
183  inline bool isNull(void) const { return pRep == 0; }
184 
185  inline void setNull(void) {
186  if (pRep)
187  {
188  // can't scope lock mutex before release in case deleted
189  release();
190  pRep = 0;
191  pUseCount = 0;
192  }
193  }
194 
195  protected:
196 
197  inline void release(void)
198  {
199  bool destroyThis = false;
200 
201  /* If the mutex is not initialized to a non-zero value, then
202  neither is pUseCount nor pRep.
203  */
204 
206  {
207  // lock own mutex in limited scope (must unlock before destroy)
209  if (pUseCount)
210  {
211  if (--(*pUseCount) == 0)
212  {
213  destroyThis = true;
214  }
215  }
216  }
217  if (destroyThis)
218  destroy();
219 
221  }
222 
223  virtual void destroy(void)
224  {
225  // IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS
226  // BEFORE SHUTTING OGRE DOWN
227  // Use setNull() before shutdown or make sure your pointer goes
228  // out of scope before OGRE shuts down to avoid this.
229  switch(useFreeMethod)
230  {
231  case SPFM_DELETE:
233  break;
234  case SPFM_DELETE_T:
236  break;
237  case SPFM_FREE:
239  break;
240  };
241  // use OGRE_FREE instead of OGRE_DELETE_T since 'unsigned int' isn't a destructor
242  // we only used OGRE_NEW_T to be able to use constructor
245  }
246 
247  virtual void swap(SharedPtr<T> &other)
248  {
249  std::swap(pRep, other.pRep);
250  std::swap(pUseCount, other.pUseCount);
251  std::swap(useFreeMethod, other.useFreeMethod);
252 #if OGRE_THREAD_SUPPORT
253  std::swap(OGRE_AUTO_MUTEX_NAME, other.OGRE_AUTO_MUTEX_NAME);
254 #endif
255  }
256  };
257 
258  template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b)
259  {
260  return a.get() == b.get();
261  }
262 
263  template<class T, class U> inline bool operator!=(SharedPtr<T> const& a, SharedPtr<U> const& b)
264  {
265  return a.get() != b.get();
266  }
267 
268  template<class T, class U> inline bool operator<(SharedPtr<T> const& a, SharedPtr<U> const& b)
269  {
270  return std::less<const void*>()(a.get(), b.get());
271  }
274 }
275 
276 
277 
278 #endif
SharedPtrFreeMethod useFreeMethod
Definition: OgreSharedPtr.h:65
virtual void swap(SharedPtr< T > &other)
T * getPointer() const
virtual void destroy(void)
#define OGRE_NEW_AUTO_SHARED_MUTEX
T * get() const
SharedPtr & operator=(const SharedPtr &r)
#define OGRE_MUTEX_CONDITIONAL(name)
SharedPtr(const SharedPtr &r)
Definition: OgreSharedPtr.h:93
bool unique() const
Use OGRE_DELETE_T to free (only MEMCATEGORY_GENERAL supported)
Definition: OgreSharedPtr.h:47
void bind(T *rep, SharedPtrFreeMethod inFreeMethod=SPFM_DELETE)
Binds rep to the SharedPtr.
#define OGRE_NEW_T(T, category)
Allocate space for one primitive type, external type or non-virtual type with constructor parameters...
#define OGRE_SET_AUTO_SHARED_MUTEX_NULL
SharedPtrFreeMethod freeMethod() const
T & operator*() const
void setNull(void)
SharedPtr(Y *rep, SharedPtrFreeMethod inFreeMethod=SPFM_DELETE)
Constructor.
Definition: OgreSharedPtr.h:82
#define OGRE_AUTO_SHARED_MUTEX
unsigned int * pUseCount
Definition: OgreSharedPtr.h:64
void release(void)
SharedPtr(const SharedPtr< Y > &r)
Use OGRE_DELETE to free the memory.
Definition: OgreSharedPtr.h:45
#define OGRE_DELETE
#define OGRE_LOCK_AUTO_SHARED_MUTEX
unsigned int useCount() const
Use OGRE_FREE to free (only MEMCATEGORY_GENERAL supported)
Definition: OgreSharedPtr.h:49
#define OGRE_LOCK_MUTEX(name)
OGRE_AUTO_SHARED_MUTEX SharedPtr()
Constructor, does not initialise the SharedPtr.
Definition: OgreSharedPtr.h:72
#define OGRE_FREE(ptr, category)
Free the memory allocated with OGRE_MALLOC or OGRE_ALLOC_T. Category is required to be restated to en...
SharedPtrFreeMethod
The method to use to free memory on destruction.
Definition: OgreSharedPtr.h:42
unsigned int * useCountPointer() const
#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...
Reference-counted shared pointer, used for objects where implicit destruction is required.
Definition: OgreSharedPtr.h:60
T * operator->() const
SharedPtr & operator=(const SharedPtr< Y > &r)
#define OGRE_DELETE_AUTO_SHARED_MUTEX
#define OGRE_COPY_AUTO_SHARED_MUTEX(from)
virtual ~SharedPtr()
bool operator==(STLAllocator< T, P > const &, STLAllocator< T2, P > const &)
determine equality, can memory from another allocator be released by this allocator, (ISO C++)
bool isNull(void) const
#define OGRE_AUTO_MUTEX_NAME
bool operator!=(STLAllocator< T, P > const &, STLAllocator< T2, P > const &)
determine equality, can memory from another allocator be released by this allocator, (ISO C++)