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 /// using FooHandle = UT_IntrusivePtr<Foo>;
49 /// @endcode
50 /// @see UT_SharedPtr
51 template<class T>
52 class UT_IntrusivePtr : public hboost::intrusive_ptr<T>
53 {
54 public:
56  UT_IntrusivePtr() noexcept
57  : hboost::intrusive_ptr<T>() {}
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 
83  template <typename Y>
86  : hboost::intrusive_ptr<T>(std::move(p)) {}
87 
90  {
91  hboost::intrusive_ptr<T>::operator=(that);
92  return *this;
93  }
94 
95  template <typename Y>
98  {
99  hboost::intrusive_ptr<T>::operator=(that);
100  return *this;
101  }
102 
105  {
106  hboost::intrusive_ptr<T>::operator=(std::move(that));
107  return *this;
108  }
109 
110  template <typename Y>
113  {
114  hboost::intrusive_ptr<T>::operator=(std::move(that));
115  return *this;
116  }
117 };
118 
119 /// Constructs an object of type T wrapped in a UT_IntrusivePtr
120 template <typename T, typename... ArgsT>
122 UTmakeIntrusive(ArgsT &&... args)
123 {
124  return UT_IntrusivePtr<T>(new T(std::forward<ArgsT>(args)...));
125 }
126 
127 /// Thread-safe policy for UT_IntrusiveRefCounter
129 {
131  using pod_type = uint32;
132 
134  static uint32 load(const type& counter) noexcept
135  {
136  return counter.relaxedLoad();
137  }
138 
140  static void increment(type& counter) noexcept
141  {
142  (void)counter.add(1);
143  }
145  static void increment(type& counter, pod_type refs_to_add) noexcept
146  {
147  (void)counter.add(refs_to_add);
148  }
149 
151  static uint32 decrement(type& counter) noexcept
152  {
153  return counter.add(-1);
154  }
156  static uint32 decrement(type& counter, pod_type refs_to_remove) noexcept
157  {
158  return counter.add(-int32(refs_to_remove));
159  }
160 };
161 
162 /// NON Thread-safe policy for UT_IntrusiveRefCounter
164 {
165  using type = uint32;
166  using pod_type = uint32;
167 
169  static uint32 load(const type& counter) noexcept { return counter; }
170 
172  static void increment(type& counter) noexcept
173  {
174  ++counter;
175  }
177  static void increment(type& counter, pod_type refs_to_add) noexcept
178  {
179  counter += refs_to_add;
180  }
181 
183  static uint32 decrement(type& counter) noexcept
184  {
185  return (--counter);
186  }
188  static uint32 decrement(type& counter, pod_type refs_to_remove) noexcept
189  {
190  return (counter -= refs_to_remove);
191  }
192 };
193 
194 // Forward declarations for friends.
195 template <
196  typename DerivedT,
197  typename Deleter = std::default_delete<DerivedT>,
198  typename CounterPolicyT = UT_IntrusiveThreadSafeCounterPolicy
199 >
201 
202 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
205 
206 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
209 
210 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
213  typename CounterPolicyT::pod_type refs_to_add) noexcept;
214 
215 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
218  typename CounterPolicyT::pod_type refs_to_remove) noexcept;
219 
220 /// @brief A reference counter base class for use with UT_IntrusivePtr
221 ///
222 /// This base class can be used with user-defined classes to add support for
223 /// @c UT_IntrusivePtr. The class contains a reference counter defined by the
224 /// @c CounterPolicyT. Upon releasing the last @c UT_IntrusivePtr referencing
225 /// the object derived from the @c UT_IntrusiveRefCounter class, operator
226 /// @c delete is automatically called on the pointer to the object.
227 ///
228 /// The other template parameter, @c DerivedT, is the user's class that
229 /// derives from @c UT_IntrusiveRefCounter.
230 ///
231 /// Example: @code
232 /// class MyClass : public UT_IntrusiveRefCounter<MyClass>
233 /// { ... };
234 /// using MyClassPtr = UT_IntrusivePtr<MyClass>;
235 /// @endcode
236 template <
237  typename DerivedT,
238  typename Deleter,
239  typename CounterPolicyT
240 >
242 {
243 public:
244  /// Default constructor: Sets counter to 0.
247  : myRefCount(0)
248  {
249  }
250  /// Copy constructor: Sets counter to 0.
253  : myRefCount(0)
254  {
255  }
256  /// Assignment operator: Does not modify counter.
258  {
259  return *this;
260  }
261  /// Return current counter
263  uint32 use_count() const noexcept
264  {
265  return CounterPolicyT::load(myRefCount);
266  }
267 
268 protected:
269  /// Destructor: Only derived classes can destruct this.
272  {
273  }
274 
275 private:
276  mutable typename CounterPolicyT::type myRefCount;
277 
278  friend void intrusive_ptr_add_ref<DerivedT,Deleter,CounterPolicyT>(
280  ) noexcept;
281  friend void intrusive_ptr_release<DerivedT,Deleter,CounterPolicyT>(
283  ) noexcept;
284  friend void intrusive_ptr_add_ref<DerivedT,Deleter,CounterPolicyT>(
286  typename CounterPolicyT::pod_type refs_to_add) noexcept;
287  friend void intrusive_ptr_release<DerivedT,Deleter,CounterPolicyT>(
289  typename CounterPolicyT::pod_type refs_to_remove) noexcept;
290 
291 };
292 
293 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
294 SYS_FORCE_INLINE void
297 {
298  CounterPolicyT::increment(p->myRefCount);
299 }
300 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
301 SYS_FORCE_INLINE void
304 {
305  if (CounterPolicyT::decrement(p->myRefCount) == 0)
306  {
307  Deleter d;
308  d(SYSconst_cast(static_cast<const DerivedT *>(p)));
309  }
310 }
311 
312 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
313 SYS_FORCE_INLINE void
316  typename CounterPolicyT::pod_type refs_to_add) noexcept
317 {
318  CounterPolicyT::increment(p->myRefCount, refs_to_add);
319 }
320 template <typename DerivedT, typename Deleter, typename CounterPolicyT>
321 SYS_FORCE_INLINE void
324  typename CounterPolicyT::pod_type refs_to_remove) noexcept
325 {
326  if (CounterPolicyT::decrement(p->myRefCount, refs_to_remove) == 0)
327  {
328  Deleter d;
329  d(SYSconst_cast(static_cast<const DerivedT *>(p)));
330  }
331 }
332 
333 // For UT::ArraySet.
334 namespace UT
335 {
336 template <typename T>
337 struct DefaultClearer;
338 
339 template <typename T>
341 {
342  static void clear(UT_IntrusivePtr<T> &v)
343  { v = UT_IntrusivePtr<T>(); }
344  static bool isClear(const UT_IntrusivePtr<T> &v)
345  { return v.get() == nullptr; }
347  { new ((void *)p) UT_IntrusivePtr<T>(nullptr); }
348  static const bool clearNeedsDestruction = false;
349 };
350 } // namespace UT
351 
352 #endif // __UT_INTRUSIVEPTR_H_INCLUDED__
SYS_FORCE_INLINE UT_IntrusivePtr(T *p, bool add_ref)
int int32
Definition: SYS_Types.h:39
static SYS_FORCE_INLINE void increment(type &counter, pod_type refs_to_add) noexcept
static SYS_FORCE_INLINE void increment(type &counter, pod_type refs_to_add) noexcept
SYS_FORCE_INLINE UT_IntrusivePtr() noexcept
const Args & args
Definition: printf.h:628
void intrusive_ptr_release(const UT_IntrusiveRefCounter< DerivedT, Deleter, CounterPolicyT > *p) noexcept
static SYS_FORCE_INLINE void increment(type &counter) noexcept
UT_IntrusivePtr< T > UTmakeIntrusive(ArgsT &&...args)
Constructs an object of type T wrapped in a UT_IntrusivePtr.
SYS_FORCE_INLINE UT_IntrusivePtr(T *p)
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
Definition: SYS_Types.h:136
SYS_AtomicInt< int32 > SYS_AtomicInt32
Definition: SYS_AtomicInt.h:82
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.
void intrusive_ptr_add_ref(const UT_IntrusiveRefCounter< DerivedT, Deleter, CounterPolicyT > *p) noexcept
NON Thread-safe policy for UT_IntrusiveRefCounter.
UT_IntrusiveRefCounter & operator=(const UT_IntrusiveRefCounter &) noexcept
Assignment operator: Does not modify counter.
static bool isClear(const UT_IntrusivePtr< T > &v)
SYS_FORCE_INLINE uint32 use_count() const noexcept
Return current counter.
#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
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)
SYS_FORCE_INLINE UT_IntrusiveRefCounter(const UT_IntrusiveRefCounter &) noexcept
Copy constructor: Sets counter to 0.
SYS_FORCE_INLINE UT_IntrusivePtr< T > & operator=(UT_IntrusivePtr< Y > &&that)
static void clearConstruct(UT_IntrusivePtr< T > *p)
GLfloat GLfloat p
Definition: glew.h:16321
static SYS_FORCE_INLINE uint32 decrement(type &counter, pod_type refs_to_remove) noexcept
static void clear(UT_IntrusivePtr< T > &v)
GLuint counter
Definition: glew.h:2740
SYS_FORCE_INLINE UT_IntrusivePtr(UT_IntrusivePtr< T > &&p)
static SYS_FORCE_INLINE uint32 decrement(type &counter, pod_type refs_to_remove) noexcept
static SYS_FORCE_INLINE uint32 decrement(type &counter) noexcept
static SYS_FORCE_INLINE uint32 load(const type &counter) noexcept
unsigned int uint32
Definition: SYS_Types.h:40
SYS_FORCE_INLINE ~UT_IntrusiveRefCounter()
Destructor: Only derived classes can destruct this.
#define const
Definition: zconf.h:214
SYS_FORCE_INLINE UT_IntrusivePtr< T > & operator=(const UT_IntrusivePtr< Y > &that)
SYS_FORCE_INLINE UT_IntrusiveRefCounter() noexcept
Default constructor: Sets counter to 0.
static SYS_FORCE_INLINE uint32 decrement(type &counter) noexcept
SYS_FORCE_INLINE UT_IntrusivePtr(UT_IntrusivePtr< Y > &&p)
static SYS_FORCE_INLINE uint32 load(const type &counter) noexcept
Thread-safe policy for UT_IntrusiveRefCounter.
type
Definition: core.h:528
static SYS_FORCE_INLINE void increment(type &counter) noexcept
A simple intrusive pointer, modeled after std::shared_ptr.
Definition: refcnt.h:53