HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UI_XPtr.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: UI_XPtr.h (UI Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __UI_XPTR_H_INCLUDED__
12 #define __UI_XPTR_H_INCLUDED__
13 
14 #include <UT/UT_Assert.h>
15 #include <SYS/SYS_Compiler.h>
16 #include <SYS/SYS_Deprecated.h>
17 #include <SYS/SYS_Inline.h>
18 #include <SYS/SYS_TypeTraits.h>
19 #include <stddef.h>
20 
21 class UI_Look;
22 
23 /// Smart pointer class for holding UI_Look instances.
24 /// Similar to a UT_UniquePtr, it additionally tracks whether its pointer is an
25 /// owner or not.
26 template <typename T>
27 class UI_XPtr
28 {
29 public:
30  using PointerType = T*;
31  using ElementType = T;
33 
35  UI_XPtr() noexcept = default;
36 
37  /// Construct via raw pointer with ownership flag
39  UI_XPtr(T *ptr, bool owner) noexcept;
40 
41  /// Construct with nullptr
42  UI_XPtr(std::nullptr_t) noexcept {};
43 
45  ~UI_XPtr();
46 
47  template <typename U>
49  UI_XPtr(UI_XPtr<U> &&other) noexcept;
50 
51  template <typename U>
53  UI_XPtr&
54  operator=(UI_XPtr<U> &&other) noexcept;
55 
56  UI_XPtr(const ThisType &other) = delete;
57  UI_XPtr& operator=(const ThisType &other) = delete;
58 
59  /// Assign nullptr
60  UI_XPtr &operator=(std::nullptr_t) noexcept
61  {
62  reset();
63  return *this;
64  }
65 
66  /// Explicit bool operator to avoid releasing the pointer with the cast
67  /// operator. To do this, we must have both const and non-const versions.
68  /// @{
70  explicit operator bool() const noexcept { return myPtr != nullptr; }
72  explicit operator bool() noexcept { return myPtr != nullptr; }
73  /// @}
74 
76  bool operator==(const ThisType &other) const noexcept
77  { return myPtr == other.myPtr; }
78 
80  bool operator!=(const ThisType &other) const noexcept
81  { return !(*this == other); }
82 
84  T &operator*() const noexcept { return *myPtr; }
85 
87  T *operator->() const noexcept { return myPtr; }
88 
90  T *get() const noexcept { return myPtr; }
91 
92  /// Release ownership and return current value
93  /// @note Unlike UT_UniquePtr, release() does not reset myPtr
95  T *release() noexcept { myIsOwner = false; return myPtr; }
96 
97  /// Reset pointer to nullptr or to another raw pointer value
98  /// @{
100  void reset() noexcept;
102  void reset(T *ptr, bool owner) noexcept;
103  /// @}
104 
105  /// Return an unowned reference to the underlying pointer
107  ThisType ref() const noexcept
108  {
109  return ThisType(myPtr, false);
110  }
111 
112  /// Determine if this is an owning pointer
114  bool isOwner() const noexcept { return myIsOwner; }
115 
116  /// Swap with another instance
117  /// @{
119  void swap(ThisType &b) noexcept
120  {
121  UI_Look* ptr = myPtr;
122  myPtr = b.myPtr;
123  b.myPtr = ptr;
124 
125  bool owner = myIsOwner;
126  myIsOwner = b.myIsOwner;
127  b.myIsOwner = owner;
128  }
130  friend void swap(ThisType &a, ThisType &b) noexcept
131  {
132  a.swap(b);
133  }
134  /// @}
135 
136 private:
137  T *myPtr = nullptr;
138  bool myIsOwner = false;
139 };
140 
141 /// Convenience method to create an UI_LookXPtr compatible subclass instance
142 template <typename T, class... Args>
143 static inline UI_XPtr<T>
144 UImakeLook(Args&&... args)
145 {
146  return UI_XPtr<T>(new T(std::forward<Args>(args)...), true);
147 }
148 
149 /////////////////////////////////////////////////////////////////////////////
150 //
151 // Inline Implementations
152 //
153 
154 template <typename T>
156 UI_XPtr<T>::UI_XPtr(T *ptr, bool owner) noexcept
157  : myPtr(ptr)
158  , myIsOwner(owner)
159 {
160  if constexpr (SYS_IsSame_v<T, UI_Look>)
161  {
162  // There should never be an owning ptr for a static look
163  UT_ASSERT(!(owner && ptr->isStatic()));
164  }
165 }
166 
167 template <typename T>
170 {
171  if (myIsOwner)
172  delete myPtr;
173 }
174 
175 template <typename T>
176 template <typename U>
179 {
180  // Steal ownership but do not reset 'other'
181  myIsOwner = other.isOwner();
182  myPtr = other.release();
183 }
184 
185 template <typename T>
186 template <typename U>
188 UI_XPtr<T>&
190 {
191  // If 'other' has the same underlying raw pointer as myPtr, we do NOT want
192  // to free prematurely if we had ownership. This is bug in the calling
193  // code. The exception we make here is if both are also non-owners because
194  // then we're likely just assigning shared looks.
195  //
196  // If myIsOwner is true and other.isOwner() false, then this case will
197  // cause us to lose ownership. In this bad situation, we will leak.
198  // Since we don't know if the caller has given ownership to someone else,
199  // we leak instead of potentially crashing with a double free.
200  UT_ASSERT((!myIsOwner && !other.isOwner()) || myPtr != other.get());
201 
202  // Delete old pointer, ensuring that we do not delete ourselves
203  if (myIsOwner && myPtr != other.get())
204  delete myPtr;
205 
206  // Steal ownership but do not reset 'other'
207  myIsOwner = other.isOwner();
208  myPtr = other.release();
209 
210  return *this;
211 }
212 
213 template <typename T>
215 void
217 {
218  if (myIsOwner)
219  delete myPtr;
220  myPtr = nullptr;
221  myIsOwner = false;
222 }
223 
224 template <typename T>
226 void
227 UI_XPtr<T>::reset(T *ptr, bool owner) noexcept
228 {
229  if (myIsOwner)
230  delete myPtr;
231  myPtr = ptr;
232  myIsOwner = owner;
233 }
234 
235 #endif // __UI_XPTR_H_INCLUDED__
SYS_FORCE_INLINE UI_XPtr & operator=(UI_XPtr< U > &&other) noexcept
SYS_FORCE_INLINE void swap(ThisType &b) noexcept
Definition: UI_XPtr.h:119
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GUI_SceneLook ElementType
Definition: UI_XPtr.h:31
GUI_SceneLook * PointerType
Definition: UI_XPtr.h:30
SYS_FORCE_INLINE friend void swap(ThisType &a, ThisType &b) noexcept
Definition: UI_XPtr.h:130
SYS_FORCE_INLINE UI_XPtr() noexcept=default
GLboolean reset
Definition: glad.h:5138
GLint ref
Definition: glcorearb.h:124
UI_XPtr< T > ThisType
Definition: UI_XPtr.h:32
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
SYS_FORCE_INLINE bool operator==(const ThisType &other) const noexcept
Definition: UI_XPtr.h:76
SYS_FORCE_INLINE bool isOwner() const noexcept
Determine if this is an owning pointer.
Definition: UI_XPtr.h:114
#define SYS_NO_DISCARD_RESULT
Definition: SYS_Compiler.h:93
SYS_FORCE_INLINE void reset() noexcept
Definition: UI_XPtr.h:216
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
SYS_FORCE_INLINE T * operator->() const noexcept
Definition: UI_XPtr.h:87
SYS_FORCE_INLINE ~UI_XPtr()
Definition: UI_XPtr.h:169
SYS_FORCE_INLINE T * release() noexcept
Definition: UI_XPtr.h:95
SYS_FORCE_INLINE bool operator!=(const ThisType &other) const noexcept
Definition: UI_XPtr.h:80
auto ptr(T p) -> const void *
Definition: format.h:2448
**If you just want to fire and args
Definition: thread.h:609
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
SYS_FORCE_INLINE T & operator*() const noexcept
Definition: UI_XPtr.h:84