HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_IntrusivePtr.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_IntrusivePtr.h (UT Library, C++)
7  *
8  * COMMENTS: A wrapper around hboost::intrusive_ptr.
9  *
10  */
11 
12 #ifndef __UT_INTRUSIVEPTR_H_INCLUDED__
13 #define __UT_INTRUSIVEPTR_H_INCLUDED__
14 
15 #include <SYS/SYS_AtomicInt.h>
16 #include <SYS/SYS_Inline.h>
17 #include <SYS/SYS_Types.h>
18 #include <memory> // For std::default_delete
19 #include <hboost/intrusive_ptr.hpp>
20 
21 /// @brief Wrapper around hboost::intrusive_ptr
22 ///
23 /// An intrusive pointer assumes that the referenced object implements
24 /// reference counting on itself. The reference counting is implemented using
25 /// the methods @c intrusive_ptr_add_ref() and @c intrusive_ptr_release().
26 ///
27 /// For simple usages, simply derive from UT_IntrusiveRefCounter.
28 ///
29 /// Here's a roll your own example: @code
30 /// class Foo {
31 /// public:
32 /// Foo() : myCount(0) {}
33 /// ~Foo() {}
34 /// void incref()
35 /// {
36 /// myCount.add(1);
37 /// }
38 /// void decref()
39 /// {
40 /// if (myCount.add(-1) == 0)
41 /// delete this;
42 /// }
43 /// SYS_AtomicInt32 myCount;
44 /// };
45 /// static inline void intrusive_ptr_add_ref(Foo *o) { o->incref(); }
46 /// static inline void intrusive_ptr_release(Foo *o) { o->decref(); }
47 ///
48 /// typedef UT_IntrusivePtr<Foo> FooHandle;
49 /// @endcode
50 /// @see UT_SharedPtr
51 template<class T>
52 class UT_IntrusivePtr : public hboost::intrusive_ptr<T>
53 {
54 public:
57  : hboost::intrusive_ptr<T>(nullptr, true) {}
58 
59  // NOTE: This should really be explicit, but there are so many
60  // places currently implicitly casting to UT_IntrusivePtr that
61  // it could take quite a while to fix.
63  /*explicit*/ UT_IntrusivePtr(T *p)
64  : hboost::intrusive_ptr<T>(p, true) {}
65 
67  UT_IntrusivePtr(T *p, bool add_ref)
68  : hboost::intrusive_ptr<T>(p, add_ref) {}
69 
72  : hboost::intrusive_ptr<T>(p) {}
73 
74  template <typename Y>
77  : hboost::intrusive_ptr<T>(p) {}
78 
81  : hboost::intrusive_ptr<T>(std::move(p)) {}
82 
85  {
86  hboost::intrusive_ptr<T>::operator=(that);
87  return *this;
88  }
89 
90  template <typename Y>
93  {
94  hboost::intrusive_ptr<T>::operator=(that);
95  return *this;
96  }
97 
100  {
101  hboost::intrusive_ptr<T>::operator=(std::move(that));
102  return *this;
103  }
104 };
105 
106 /// Thread-safe policy for UT_IntrusiveRefCounter
108 {
110  typedef uint32 pod_type;
111 
113  static uint32 load(const type& counter) { return counter.relaxedLoad();}
115  static void increment(type& counter) { (void) counter.add(1); }
117  static void increment(type& counter, pod_type refs_to_add) { (void) counter.add(refs_to_add); }
119  static uint32 decrement(type& counter) { return counter.add(-1); }
121  static uint32 decrement(type& counter, pod_type refs_to_remove) { return counter.add(-int32(refs_to_remove)); }
122 };
123 
124 /// NOT Thread-safe policy for UT_IntrusiveRefCounter
126 {
127  typedef uint32 type;
128  typedef uint32 pod_type;
129 
131  static uint32 load(const type& counter) { return counter; }
133  static void increment(type& counter) { ++counter; }
135  static void increment(type& counter, pod_type refs_to_add) { counter += refs_to_add; }
137  static uint32 decrement(type& counter) { return (--counter); }
139  static uint32 decrement(type& counter, pod_type refs_to_remove) { return (counter -= refs_to_remove); }
140 };
141 
142 // Forward declarations for friends.
143 template <
144  typename DerivedT,
145  typename Deleter = std::default_delete<DerivedT>,
146  typename CounterPolicyT = UT_IntrusiveThreadSafeCounterPolicy
147 >
149 
150 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
153 
154 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
157 
158 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
160  const UT_IntrusiveRefCounter<DerivedT,Deleter,CounterPolicyT>* p, typename CounterPolicyT::pod_type refs_to_add);
161 
162 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
164  const UT_IntrusiveRefCounter<DerivedT,Deleter,CounterPolicyT>* p, typename CounterPolicyT::pod_type refs_to_remove);
165 
166 /// @brief A reference counter base class for use with UT_IntrusivePtr
167 ///
168 /// This base class can be used with user-defined classes to add support for
169 /// @c UT_IntrusivePtr. The class contains a reference counter defined by the
170 /// @c CounterPolicyT. Upon releasing the last @c UT_IntrusivePtr referencing
171 /// the object derived from the @c UT_IntrusiveRefCounter class, operator
172 /// @c delete is automatically called on the pointer to the object.
173 ///
174 /// The other template parameter, @c DerivedT, is the user's class that
175 /// derives from @c UT_IntrusiveRefCounter.
176 ///
177 /// Example: @code
178 /// class MyClass : public UT_IntrusiveRefCounter<MyClass>
179 /// { ... };
180 /// typedef UT_IntrusivePtr<MyClass> MyClassPtr;
181 /// @endcode
182 template <
183  typename DerivedT,
184  typename Deleter,
185  typename CounterPolicyT
186 >
188 {
189 public:
190  /// Default constructor: Sets counter to 0.
193  : myRefCount(0)
194  {
195  }
196  /// Copy constructor: Sets counter to 0.
199  : myRefCount(0)
200  {
201  }
202  /// Assignment operator: Does not modify counter.
204  {
205  return *this;
206  }
207  /// Return current counter
210  {
211  return CounterPolicyT::load(myRefCount);
212  }
213 
214 protected:
215  /// Destructor: Only derived classes can destruct this.
218  {
219  }
220 
221 private:
222  mutable typename CounterPolicyT::type myRefCount;
223 
224  friend void intrusive_ptr_add_ref<DerivedT,Deleter,CounterPolicyT>(
226  friend void intrusive_ptr_release<DerivedT,Deleter,CounterPolicyT>(
228  friend void intrusive_ptr_add_ref<DerivedT,Deleter,CounterPolicyT>(
230  typename CounterPolicyT::pod_type refs_to_add);
231  friend void intrusive_ptr_release<DerivedT,Deleter,CounterPolicyT>(
233  typename CounterPolicyT::pod_type refs_to_remove);
234 
235 };
236 
237 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
238 SYS_FORCE_INLINE void
241 {
242  CounterPolicyT::increment(p->myRefCount);
243 }
244 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
245 SYS_FORCE_INLINE void
248 {
249  if (CounterPolicyT::decrement(p->myRefCount) == 0)
250  {
251  Deleter d;
252  d(SYSconst_cast(static_cast<const DerivedT *>(p)));
253  }
254 }
255 
256 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
257 SYS_FORCE_INLINE void
260  typename CounterPolicyT::pod_type refs_to_add)
261 {
262  CounterPolicyT::increment(p->myRefCount, refs_to_add);
263 }
264 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
265 SYS_FORCE_INLINE void
268  typename CounterPolicyT::pod_type refs_to_remove)
269 {
270  if (CounterPolicyT::decrement(p->myRefCount, refs_to_remove) == 0)
271  {
272  Deleter d;
273  d(SYSconst_cast(static_cast<const DerivedT *>(p)));
274  }
275 }
276 
277 // For UT::ArraySet.
278 namespace UT
279 {
280 template <typename T>
281 struct DefaultClearer;
282 
283 template <typename T>
285 {
286  static void clear(UT_IntrusivePtr<T> &v)
287  { v = UT_IntrusivePtr<T>(); }
288  static bool isClear(const UT_IntrusivePtr<T> &v)
289  { return v.get() == nullptr; }
291  { new ((void *)p) UT_IntrusivePtr<T>(nullptr); }
292  static const bool clearNeedsDestruction = false;
293 };
294 } // namespace UT
295 
296 #endif // __UT_INTRUSIVEPTR_H_INCLUDED__
SYS_FORCE_INLINE UT_IntrusivePtr(T *p, bool add_ref)
SYS_FORCE_INLINE uint32 use_count() const
Return current counter.
SYS_FORCE_INLINE UT_IntrusivePtr(T *p)
static SYS_FORCE_INLINE uint32 decrement(type &counter)
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
Definition: SYS_Types.h:131
static SYS_FORCE_INLINE void increment(type &counter, pod_type refs_to_add)
SYS_FORCE_INLINE UT_IntrusivePtr(const UT_IntrusivePtr< Y > &p)
const GLdouble * v
Definition: glew.h:1391
A reference counter base class for use with UT_IntrusivePtr.
UT_IntrusiveRefCounter & operator=(const UT_IntrusiveRefCounter &)
Assignment operator: Does not modify counter.
NOT Thread-safe policy for UT_IntrusiveRefCounter.
static bool isClear(const UT_IntrusivePtr< T > &v)
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
SYS_FORCE_INLINE UT_IntrusivePtr< T > & operator=(UT_IntrusivePtr< T > &&that)
void
Definition: png.h:1083
static SYS_FORCE_INLINE uint32 decrement(type &counter, pod_type refs_to_remove)
static SYS_FORCE_INLINE uint32 load(const type &counter)
SYS_FORCE_INLINE UT_IntrusivePtr< T > & operator=(const UT_IntrusivePtr< T > &that)
Wrapper around hboost::intrusive_ptr.
SYS_FORCE_INLINE UT_IntrusivePtr(const UT_IntrusivePtr< T > &p)
static SYS_FORCE_INLINE void increment(type &counter, pod_type refs_to_add)
static void clearConstruct(UT_IntrusivePtr< T > *p)
int int32
Definition: SYS_Types.h:39
void intrusive_ptr_add_ref(const UT_IntrusiveRefCounter< DerivedT, Deleter, CounterPolicyT > *p)
SYS_FORCE_INLINE UT_IntrusiveRefCounter(const UT_IntrusiveRefCounter &)
Copy constructor: Sets counter to 0.
GLfloat GLfloat p
Definition: glew.h:16321
static void clear(UT_IntrusivePtr< T > &v)
GLuint counter
Definition: glew.h:2740
SYS_FORCE_INLINE UT_IntrusivePtr(UT_IntrusivePtr< T > &&p)
SYS_FORCE_INLINE UT_IntrusivePtr()
T add(T val)
Atomically adds val to myValue, returning the new value of myValue.
static SYS_FORCE_INLINE void increment(type &counter)
SYS_FORCE_INLINE ~UT_IntrusiveRefCounter()
Destructor: Only derived classes can destruct this.
static SYS_FORCE_INLINE uint32 decrement(type &counter, pod_type refs_to_remove)
SYS_FORCE_INLINE UT_IntrusivePtr< T > & operator=(const UT_IntrusivePtr< Y > &that)
static SYS_FORCE_INLINE uint32 decrement(type &counter)
void intrusive_ptr_release(const UT_IntrusiveRefCounter< DerivedT, Deleter, CounterPolicyT > *p)
SYS_FORCE_INLINE T relaxedLoad() const
Definition: SYS_AtomicInt.h:57
Thread-safe policy for UT_IntrusiveRefCounter.
static SYS_FORCE_INLINE void increment(type &counter)
type
Definition: core.h:528
static SYS_FORCE_INLINE uint32 load(const type &counter)
A simple intrusive pointer, modeled after std::shared_ptr.
Definition: refcnt.h:53
unsigned int uint32
Definition: SYS_Types.h:40
SYS_FORCE_INLINE UT_IntrusiveRefCounter()
Default constructor: Sets counter to 0.