Nebula
Loading...
Searching...
No Matches
ptr.h
Go to the documentation of this file.
1#pragma once
2//------------------------------------------------------------------------------
16#include "core/types.h"
17#include "math/scalar.h"
18
19// platform secific stuff for handling/suppress "unused-argument"-warnings
20#if NEBULA_DEBUG
21#if __WIN32__
22#pragma warning( push )
23// warning unused param
24#pragma warning(disable: 4189)
25#endif
26
27#define NEBULA_UNUSED_ATTR
28#endif // NEBULA_DEBUG
29
30namespace Core
31{
32 class RefCounted;
33}
34
35//------------------------------------------------------------------------------
36template<class TYPE>
37class Ptr
38{
39public:
41 Ptr();
43 Ptr(TYPE* p);
45 Ptr(std::nullptr_t rhs);
47 Ptr(const Ptr<TYPE>& p);
50
52 template <class OTHERTYPE>
53 friend class Ptr;
54
56 template<class OTHERTYPE>
57 Ptr(OTHERTYPE* rhs) : ptr(nullptr)
58 {
59 this->ptr = nullptr;
60 static_assert(std::is_base_of<TYPE, OTHERTYPE>::value, "Implicit cast assumes left hand side must be base of right");
61 TYPE* p = reinterpret_cast<TYPE*>(rhs);
62 if (p != this->ptr)
63 {
64 this->ptr = p;
65 if (this->ptr)
66 this->ptr->AddRef();
67 }
68 }
70 template <class OTHERTYPE>
71 Ptr(const Ptr<OTHERTYPE>& rhs) : ptr(nullptr)
72 {
73 this->ptr = nullptr;
74 static_assert(std::is_base_of<TYPE, OTHERTYPE>::value, "Implicit cast assumes left hand side must be base of right");
75 TYPE* p = reinterpret_cast<TYPE*>(rhs.ptr);
76 if (p != this->ptr)
77 {
78 this->ptr = p;
79 if (nullptr != this->ptr)
80 this->ptr->AddRef();
81 }
82 }
84 template <class OTHERTYPE>
86 {
87 this->ptr = nullptr;
88 static_assert(std::is_base_of<TYPE, OTHERTYPE>::value, "Implicit cast assumes left hand side must be base of right");
89 TYPE* p = reinterpret_cast<TYPE*>(rhs.ptr);
90 this->ptr = p;
91 rhs.ptr = nullptr;
92 }
96 void operator=(TYPE* rhs);
98 void operator=(const Ptr<TYPE>& rhs);
100 void operator=(Ptr<TYPE>&& rhs);
102 void operator=(std::nullptr_t rhs);
103
105 template<class OTHERTYPE>
106 void operator=(OTHERTYPE* rhs)
107 {
108 static_assert(std::is_base_of<TYPE, OTHERTYPE>::value, "Implicit assignment assumes left hand side must be base of right");
109 TYPE* p = reinterpret_cast<TYPE*>(rhs);
110 if (this->ptr != p)
111 {
112 if (this->ptr != nullptr)
113 this->ptr->Release();
114 this->ptr = p;
115 if (this->ptr != nullptr) this->ptr->AddRef();
116 }
117 }
119 template<class OTHERTYPE>
120 void operator=(const Ptr<OTHERTYPE>& rhs)
121 {
122 static_assert(std::is_base_of<TYPE, OTHERTYPE>::value, "Implicit assignment assumes left hand side must be base of right");
123 TYPE* p = reinterpret_cast<TYPE*>(rhs.ptr);
124 if (this->ptr != p)
125 {
126 if (this->ptr != nullptr)
127 this->ptr->Release();
128 this->ptr = p;
129 if (this->ptr != nullptr) this->ptr->AddRef();
130 }
131 }
133 template<class OTHERTYPE>
135 {
136 static_assert(std::is_base_of<TYPE, OTHERTYPE>::value, "Implicit assignment assumes left hand side must be base of right");
137 TYPE* p = reinterpret_cast<TYPE*>(rhs.ptr);
138 if (this->ptr != p)
139 {
140 if (this->ptr != nullptr)
141 this->ptr->Release();
142 this->ptr = p;
143 rhs.ptr = nullptr;
144 }
145 }
146
148 bool operator==(const Ptr<TYPE>& rhs) const;
150 bool operator!=(const Ptr<TYPE>& rhs) const;
152 bool operator==(const TYPE* rhs) const;
154 bool operator!=(const TYPE* rhs) const;
156 TYPE* operator->() const;
158 TYPE& operator*() const;
160 operator TYPE*() const;
162 template<class DERIVED> const Ptr<DERIVED>& downcast() const;
164 template<class BASE> const Ptr<BASE>& upcast() const;
167 template<class OTHERTYPE> const Ptr<OTHERTYPE>& cast() const;
169 bool isvalid() const;
171 TYPE* get() const;
173 TYPE* get_unsafe() const;
174
176 uint32_t HashCode() const;
177
178private:
179 TYPE* ptr;
180};
181
182//------------------------------------------------------------------------------
185template<class TYPE>
187 ptr(0)
188{
189 // empty
190}
191
192//------------------------------------------------------------------------------
195template<class TYPE>
197 ptr(p)
198{
199 //static_assert(std::is_base_of<Core::RefCounted, TYPE>::value, "Ptr only works on RefCounted types");
200 if (0 != this->ptr)
201 {
202 this->ptr->AddRef();
203 }
204}
205
206//------------------------------------------------------------------------------
209template<class TYPE>
210inline Ptr<TYPE>::Ptr(std::nullptr_t rhs) :
211 ptr(nullptr)
212{
213}
214
215//------------------------------------------------------------------------------
218template<class TYPE>
220 ptr(p.ptr)
221{
222 if (0 != this->ptr)
223 {
224 this->ptr->AddRef();
225 }
226}
227
228//------------------------------------------------------------------------------
231template<class TYPE>
233 ptr(p.ptr)
234{
235 p.ptr = nullptr;
236}
237
238//------------------------------------------------------------------------------
241template<class TYPE>
243{
244 if (0 != this->ptr)
245 {
246 this->ptr->Release();
247 this->ptr = 0;
248 }
249}
250
251//------------------------------------------------------------------------------
254template<class TYPE>
255void
257{
258 if (this->ptr != rhs)
259 {
260 if (this->ptr != nullptr)
261 this->ptr->Release();
262 this->ptr = rhs;
263 if (this->ptr != nullptr)
264 this->ptr->AddRef();
265 }
266}
267
268//------------------------------------------------------------------------------
271template<class TYPE>
272void
274{
275 if (this->ptr != rhs.ptr)
276 {
277 if (this->ptr != nullptr)
278 this->ptr->Release();
279 this->ptr = rhs.ptr;
280 if (this->ptr != nullptr)
281 this->ptr->AddRef();
282 }
283}
284
285//------------------------------------------------------------------------------
288template<class TYPE>
289void
291{
292 if (this->ptr != rhs.ptr)
293 {
294 if (this->ptr)
295 this->ptr->Release();
296 this->ptr = rhs.ptr;
297 rhs.ptr = nullptr;
298 }
299}
300
301//------------------------------------------------------------------------------
304template<class TYPE>
305inline void
306Ptr<TYPE>::operator=(std::nullptr_t rhs)
307{
308 if (this->ptr != rhs)
309 {
310 if (this->ptr != nullptr) this->ptr->Release();
311 this->ptr = rhs;
312 }
313}
314
315//------------------------------------------------------------------------------
318template<class TYPE>
319bool
321{
322 return (this->ptr == rhs.ptr);
323}
324
325//------------------------------------------------------------------------------
328template<class TYPE>
329bool
331{
332 return (this->ptr != rhs.ptr);
333}
334
335//------------------------------------------------------------------------------
338template<class TYPE>
339bool
340Ptr<TYPE>::operator==(const TYPE* rhs) const
341{
342 return (this->ptr == rhs);
343}
344
345//------------------------------------------------------------------------------
348template<class TYPE>
349bool
350Ptr<TYPE>::operator!=(const TYPE* rhs) const
351{
352 return (this->ptr != rhs);
353}
354
355//------------------------------------------------------------------------------
358template<class TYPE>
359TYPE*
361{
362 n_assert2(this->ptr, "NULL pointer access in Ptr::operator->()!");
363 return this->ptr;
364}
365
366//------------------------------------------------------------------------------
369template<class TYPE>
370TYPE&
372{
373 n_assert2(this->ptr, "NULL pointer access in Ptr::operator*()!");
374 return *this->ptr;
375}
376
377//------------------------------------------------------------------------------
380template<class TYPE>
382{
383 n_assert2(this->ptr, "NULL pointer access in Ptr::operator TYPE*()!");
384 return this->ptr;
385}
386
387//------------------------------------------------------------------------------
390template<class TYPE>
391template<class DERIVED> const Ptr<DERIVED>&
393{
394#if (NEBULA_DEBUG == 1)
395 // if DERIVED is not a derived class of TYPE, compiler complains here
396 // compile-time inheritance-test
397 static_assert(std::is_base_of<TYPE, DERIVED>::value, "Incompatible types");
398#endif
399
400 return *reinterpret_cast<const Ptr<DERIVED>*>(this);
401}
402
403//------------------------------------------------------------------------------
406template<class TYPE>
407template<class BASE> const Ptr<BASE>&
409{
410#if (NEBULA_DEBUG == 1)
411 // if BASE is not a base-class of TYPE, compiler complains here
412 // compile-time inheritance-test
413 static_assert(std::is_base_of<BASE, TYPE>::value, "Incompatible types");
414#endif
415
416 return *reinterpret_cast<const Ptr<BASE>*>(this);
417}
418
419//------------------------------------------------------------------------------
422template<class TYPE>
423template<class OTHERTYPE> const Ptr<OTHERTYPE>&
425{
426 // note: this is an unsafe cast
427 return *reinterpret_cast<const Ptr<OTHERTYPE>*>(this);
428}
429
430//------------------------------------------------------------------------------
433template<class TYPE>
434bool
436{
437 return (nullptr != this->ptr);
438}
439
440//------------------------------------------------------------------------------
443template<class TYPE>
444TYPE*
446{
447 n_assert2(this->ptr, "NULL pointer access in Ptr::get()!");
448 return this->ptr;
449}
450
451//------------------------------------------------------------------------------
454template<class TYPE>
455TYPE*
457{
458 return this->ptr;
459}
460
461
462//------------------------------------------------------------------------------
465template<class TYPE>
466uint32_t
468{
469 return Math::pointerhash((void *)this->ptr);
470}
471
472//------------------------------------------------------------------------------
473
474#if __WIN32__ && NEBULA_DEBUG
475#pragma warning( pop )
476#endif
477#ifdef NEBULA_UNUSED_ATTR
478#undef NEBULA_UNUSED_ATTR
479#endif
Nebula's smart pointer class which manages the life time of RefCounted objects.
Definition ptr.h:38
TYPE & operator*() const
safe dereference operator
Definition ptr.h:371
Ptr()
constructor
Definition ptr.h:186
const Ptr< DERIVED > & downcast() const
type-safe downcast operator to other smart pointer
Definition ptr.h:392
Ptr(const Ptr< OTHERTYPE > &rhs)
construct from smart pointer of other type
Definition ptr.h:71
TYPE * operator->() const
safe -> operator
Definition ptr.h:360
Ptr(TYPE *p)
construct from C++ pointer
Definition ptr.h:196
void operator=(const Ptr< TYPE > &rhs)
assignment operator
Definition ptr.h:273
const Ptr< OTHERTYPE > & cast() const
unsafe(!) cast to anything, unless classes have no inheritance-relationship, call upcast/downcast ins...
Definition ptr.h:424
Ptr(std::nullptr_t rhs)
constructor from nullptr
Definition ptr.h:210
bool operator!=(const Ptr< TYPE > &rhs) const
inequality operator
Definition ptr.h:330
const Ptr< BASE > & upcast() const
type-safe upcast operator to other smart pointer
Definition ptr.h:408
uint32_t HashCode() const
calculate hash code for Util::HashTable (basically just the adress)
Definition ptr.h:467
void operator=(Ptr< OTHERTYPE > &&rhs)
move assignment to Ptr of other type
Definition ptr.h:134
void operator=(Ptr< TYPE > &&rhs)
move operator
Definition ptr.h:290
TYPE * get() const
return direct pointer (asserts if null pointer)
Definition ptr.h:445
Ptr(OTHERTYPE *rhs)
construct from C++ pointer of other type
Definition ptr.h:57
Ptr(Ptr< OTHERTYPE > &&rhs)
construct from smart pointer of other type
Definition ptr.h:85
bool operator!=(const TYPE *rhs) const
shortcut inequality operator
Definition ptr.h:350
~Ptr()
destructor
Definition ptr.h:242
void operator=(OTHERTYPE *rhs)
assign operator to pointer of other type
Definition ptr.h:106
bool isvalid() const
check if pointer is valid
Definition ptr.h:435
TYPE * ptr
Definition ptr.h:179
friend class Ptr
make other type Ptr classes friend
Definition ptr.h:53
TYPE * get_unsafe() const
return direct pointer (returns null pointer)
Definition ptr.h:456
void operator=(std::nullptr_t rhs)
unassignment operator
Definition ptr.h:306
bool operator==(const TYPE *rhs) const
shortcut equality operator
Definition ptr.h:340
bool operator==(const Ptr< TYPE > &rhs) const
equality operator
Definition ptr.h:320
Ptr(Ptr< TYPE > &&p)
implement move constructor
Definition ptr.h:232
void operator=(TYPE *rhs)
assignment operator
Definition ptr.h:256
void operator=(const Ptr< OTHERTYPE > &rhs)
assign operator to Ptr of other type
Definition ptr.h:120
Ptr(const Ptr< TYPE > &p)
construct from smart pointer
Definition ptr.h:219
#define n_assert2(exp, msg)
Definition debug.h:51
Definition coreserver.cc:10
__forceinline uint32_t pointerhash(void *ptr)
cheap pointer hash using modulo with a mersenne prime
Definition scalar.h:808
Nebula's scalar datatype.