UraniumCompute 0.1.0
A GPU accelerated parallel task scheduler
Ptr.h
1#pragma once
2#include <UnCompute/Memory/Object.h>
3
4namespace UN
5{
7 namespace Internal
8 {
9 template<class T>
10 class PtrRef final
11 {
12 T* m_Ptr;
13
14 public:
15 using ObjectType = typename T::ObjectType;
16
17 inline explicit PtrRef(T* ptr)
18 : m_Ptr(ptr)
19 {
20 }
21
22 inline operator ObjectType**() // NOLINT
23 {
24 return m_Ptr->ReleaseAndGetAddressOf();
25 }
26
27 inline ObjectType* operator*()
28 {
29 return m_Ptr->Get();
30 }
31 };
32 } // namespace Internal
33
42 template<class T>
43 class Ptr final
44 {
45 T* m_pObject;
46
47 template<class T1, class = void>
48 struct IsComplete : std::false_type
49 {
50 };
51
52 template<class T1>
53 struct IsComplete<T1, decltype(void(sizeof(T1)))> : std::true_type
54 {
55 };
56
57 template<class TBase, class TDerived, bool>
58 struct IsBaseOf : std::true_type
59 {
60 };
61
62 // NOTE: Check for completeness of the type is here to allow pointers that hold forward-declared classes
63 template<class TBase, class TDerived>
64 struct IsBaseOf<TBase, TDerived, true> : std::is_base_of<TBase, TDerived>
65 {
66 };
67
68 static_assert(IsBaseOf<IObject, T, IsComplete<T>::value>::value,
69 "The template parameter in Ptr<T> must be a class or an interface derived from IObject");
70
71 template<class T1>
72 friend class Ptr;
73
74 inline void InternalAddRef() const
75 {
76 if (m_pObject)
77 {
78 m_pObject->AddRef();
79 }
80 }
81
82 inline UInt32 InternalRelease()
83 {
84 UInt32 result = 0;
85 if (m_pObject)
86 {
87 result = m_pObject->Release();
88 m_pObject = nullptr;
89 }
90
91 return result;
92 }
93
94 public:
95 using ObjectType = T;
96
98 inline Ptr() noexcept
99 : m_pObject(nullptr)
100 {
101 }
102
109 inline Ptr(T* pObject) noexcept // NOLINT
110 : m_pObject(pObject)
111 {
112 InternalAddRef();
113 }
114
118 inline Ptr(const Ptr& other) noexcept
119 : m_pObject(other.m_pObject)
120 {
121 InternalAddRef();
122 }
123
127 template<class T1>
128 inline Ptr(const Ptr<T1>& other) noexcept // NOLINT
129 : m_pObject(other.Get())
130 {
131 InternalAddRef();
132 }
133
137 inline Ptr(Ptr&& other) noexcept
138 : m_pObject(other.m_pObject)
139 {
140 other.m_pObject = nullptr;
141 }
142
144 inline void Swap(Ptr& other)
145 {
146 auto* t = other.m_pObject;
147 other.m_pObject = m_pObject;
148 m_pObject = t;
149 }
150
154 inline Ptr& operator=(const Ptr& other)
155 {
156 Ptr(other).Swap(*this);
157 return *this;
158 }
159
163 inline Ptr& operator=(Ptr&& other) noexcept
164 {
165 Ptr(std::move(other)).Swap(*this);
166 return *this;
167 }
168
170 inline void Reset()
171 {
172 Ptr{}.Swap(*this);
173 }
174
175 inline ~Ptr()
176 {
177 InternalRelease();
178 }
179
181 inline T* const* GetAddressOf() const
182 {
183 return &m_pObject;
184 }
185
187 inline T** GetAddressOf()
188 {
189 return &m_pObject;
190 }
191
196 {
197 InternalRelease();
198 return &m_pObject;
199 }
200
202 inline void Attach(T* pObject)
203 {
204 InternalRelease();
205 m_pObject = pObject;
206 }
207
211 inline T* Detach()
212 {
213 T* ptr = m_pObject;
214 m_pObject = nullptr;
215 return ptr;
216 }
217
219 inline T* Get() const
220 {
221 return m_pObject;
222 }
223
225 template<class TDest>
226 inline std::enable_if_t<std::is_base_of_v<TDest, T>, TDest*> As() const
227 {
228 return static_cast<TDest*>(Get());
229 }
230
232 template<class TDest>
233 inline std::enable_if_t<std::is_base_of_v<T, TDest> && !std::is_same_v<T, TDest>, TDest*> As() const
234 {
235 return un_verify_cast<TDest*>(Get());
236 }
237
238 inline Internal::PtrRef<Ptr<T>> operator&() // NOLINT
239 {
240 return Internal::PtrRef<Ptr<T>>(this);
241 }
242
243 inline T& operator*()
244 {
245 return *Get();
246 }
247
248 inline T* operator->()
249 {
250 return Get();
251 }
252
253 inline const T& operator*() const
254 {
255 return *Get();
256 }
257
258 inline const T* operator->() const
259 {
260 return Get();
261 }
262
263 inline explicit operator bool() const
264 {
265 return m_pObject;
266 }
267 };
268
269 template<class T>
270 inline bool operator==(const Ptr<T>& lhs, std::nullptr_t)
271 {
272 return lhs.Get() == nullptr;
273 }
274
275 template<class T>
276 inline bool operator!=(const Ptr<T>& lhs, std::nullptr_t)
277 {
278 return !(lhs == nullptr);
279 }
280
281 template<class T>
282 inline bool operator==(std::nullptr_t, const Ptr<T>& rhs)
283 {
284 return rhs.Get() == nullptr;
285 }
286
287 template<class T>
288 inline bool operator!=(std::nullptr_t, const Ptr<T>& rhs)
289 {
290 return !(nullptr == rhs);
291 }
292
293 template<class T1, class T2>
294 inline bool operator==(const Ptr<T1>& lhs, T2* rhs)
295 {
296 return static_cast<IObject*>(lhs.Get()) == static_cast<IObject*>(rhs);
297 }
298
299 template<class T1, class T2>
300 inline bool operator!=(const Ptr<T1>& lhs, T2* rhs)
301 {
302 return !(lhs == rhs);
303 }
304
305 template<class T1, class T2>
306 inline bool operator==(T1* lhs, const Ptr<T2>& rhs)
307 {
308 return rhs == lhs;
309 }
310
311 template<class T1, class T2>
312 inline bool operator!=(T1* lhs, const Ptr<T2>& rhs)
313 {
314 return !(lhs == rhs);
315 }
316
317 template<class T1, class T2>
318 inline bool operator==(const Ptr<T1>& lhs, const Ptr<T2>& rhs)
319 {
320 return static_cast<IObject*>(lhs.Get()) == static_cast<IObject*>(rhs.Get());
321 }
322
323 template<class T1, class T2>
324 inline bool operator!=(const Ptr<T1>& lhs, const Ptr<T2>& rhs)
325 {
326 return !(lhs == rhs);
327 }
328
329 template<class TDest, class TSrc>
330 inline std::enable_if_t<std::is_base_of_v<TSrc, TDest>, Ptr<TDest>> un_verify_cast(const Ptr<TSrc>& pSourceObject)
331 {
332 return Ptr<TDest>(un_verify_cast<TDest*>(pSourceObject.Get()));
333 }
334} // namespace UN
Definition: Ptr.h:11
Shared smart pointer implementation that uses reference counting.
Definition: Ptr.h:44
void Attach(T *pObject)
Attach a pointer and do not add strong reference.
Definition: Ptr.h:202
Ptr(T *pObject) noexcept
Create a pointer that points to the specified object.
Definition: Ptr.h:109
std::enable_if_t< std::is_base_of_v< T, TDest > &&!std::is_same_v< T, TDest >, TDest * > As() const
Get underlying raw pointer and cast it.
Definition: Ptr.h:233
T ** GetAddressOf()
Get pointer to the underlying pointer.
Definition: Ptr.h:187
Ptr(const Ptr< T1 > &other) noexcept
Copy a pointer (adds a strong reference to underlying object).
Definition: Ptr.h:128
Ptr(Ptr &&other) noexcept
Move a pointer (doesn't add a strong reference to underlying object).
Definition: Ptr.h:137
void Swap(Ptr &other)
Swap raw pointers of two objects without incrementing and decrementing ref-counters.
Definition: Ptr.h:144
Ptr & operator=(Ptr &&other) noexcept
Move a pointer (doesn't add a strong reference to underlying object).
Definition: Ptr.h:163
T * Get() const
Get underlying raw pointer.
Definition: Ptr.h:219
T ** ReleaseAndGetAddressOf()
Release a strong reference and get pointer to the stored pointer.
Definition: Ptr.h:195
Ptr() noexcept
Create a null reference counted pointer.
Definition: Ptr.h:98
Ptr(const Ptr &other) noexcept
Copy a pointer (adds a strong reference to underlying object).
Definition: Ptr.h:118
T *const * GetAddressOf() const
Get pointer to the underlying pointer.
Definition: Ptr.h:181
T * Detach()
Forget object and don't free it automatically.
Definition: Ptr.h:211
Ptr & operator=(const Ptr &other)
Copy a pointer (adds a strong reference to underlying object).
Definition: Ptr.h:154
std::enable_if_t< std::is_base_of_v< TDest, T >, TDest * > As() const
Get underlying raw pointer and cast it.
Definition: Ptr.h:226
void Reset()
Set a pointer to null.
Definition: Ptr.h:170