cesium-native  0.41.0
IntrusivePointer.h
1 #pragma once
2 #include <type_traits>
3 #include <utility>
4 
5 namespace CesiumUtility {
6 
19 template <class T> class IntrusivePointer final {
20 public:
24  IntrusivePointer(T* p = nullptr) noexcept : _p(p) { this->addReference(); }
25 
29  IntrusivePointer(const IntrusivePointer<T>& rhs) noexcept : _p(rhs._p) {
30  this->addReference();
31  }
32 
40  template <class U>
41  IntrusivePointer(const IntrusivePointer<U>& rhs) noexcept : _p(rhs._p) {
42  this->addReference();
43  }
44 
49  : _p(std::exchange(rhs._p, nullptr)) {
50  // Reference count is unchanged
51  }
52 
60  template <class U>
62  : _p(std::exchange(rhs._p, nullptr)) {
63  // Reference count is unchanged
64  }
65 
69  ~IntrusivePointer() noexcept { this->releaseReference(); }
70 
80  template <typename... ConstructorArgumentTypes>
81  T& emplace(ConstructorArgumentTypes&&... constructorArguments) {
82  *this =
83  new T(std::forward<ConstructorArgumentTypes>(constructorArguments)...);
84  return *this->get();
85  }
86 
90  void reset() { *this = nullptr; }
91 
96  if (this->_p != rhs._p) {
97  // addReference the new pointer before releaseReference'ing the old.
98  T* pOld = this->_p;
99  this->_p = rhs._p;
100  addReference();
101 
102  if (pOld) {
103  pOld->releaseReference();
104  }
105  }
106 
107  return *this;
108  }
109  template <class U>
110  IntrusivePointer& operator=(const IntrusivePointer<U>& rhs) noexcept {
111  if (this->_p != rhs._p) {
112  // addReference the new pointer before releaseReference'ing the old.
113  T* pOld = this->_p;
114  this->_p = rhs._p;
115  addReference();
116 
117  if (pOld) {
118  pOld->releaseReference();
119  }
120  }
121 
122  return *this;
123  }
124 
129  if (this->_p != rhs._p) {
130  std::swap(this->_p, rhs._p);
131  }
132 
133  return *this;
134  }
135 
139  IntrusivePointer& operator=(T* p) noexcept {
140  if (this->_p != p) {
141  // addReference the new pointer before releaseReference'ing the old.
142  T* pOld = this->_p;
143  this->_p = p;
144  addReference();
145 
146  if (pOld) {
147  pOld->releaseReference();
148  }
149  }
150 
151  return *this;
152  }
153 
157  T& operator*() const noexcept { return *this->_p; }
158 
162  T* operator->() const noexcept { return this->_p; }
163 
168  explicit operator bool() const noexcept { return this->_p != nullptr; }
169 
173  T* get() const noexcept { return this->_p; }
174 
178  bool operator==(const IntrusivePointer<T>& rhs) const noexcept {
179  return this->_p == rhs._p;
180  }
181  template <class U>
182  bool operator==(const IntrusivePointer<U>& rhs) const noexcept {
183  return this->_p == rhs._p;
184  }
185 
189  bool operator!=(const IntrusivePointer<T>& rhs) const noexcept {
190  return !(*this == rhs);
191  }
192 
197  bool operator==(const T* pRhs) const noexcept { return this->_p == pRhs; }
198 
203  bool operator!=(const T* pRhs) const noexcept { return !(*this == pRhs); }
204 
205 private:
206  void addReference() noexcept {
207  if (this->_p) {
208  this->_p->addReference();
209  }
210  }
211 
212  void releaseReference() noexcept {
213  if (this->_p) {
214  this->_p->releaseReference();
215  }
216  }
217 
218  T* _p;
219  template <typename U> friend class IntrusivePointer;
220 };
221 
222 template <typename T, typename U>
223 IntrusivePointer<T>
224 const_intrusive_cast(const IntrusivePointer<U>& p) noexcept {
225  return IntrusivePointer<T>(const_cast<T*>(p.get()));
226 }
227 
228 } // namespace CesiumUtility
A smart pointer that calls addReference and releaseReference on the controlled object.
bool operator==(const IntrusivePointer< T > &rhs) const noexcept
Returns true if two pointers are equal.
T & emplace(ConstructorArgumentTypes &&... constructorArguments)
Constructs a new instance and assigns it to this IntrusivePointer. If this IntrusivePointer already p...
T * get() const noexcept
Returns the internal pointer.
IntrusivePointer(IntrusivePointer< T > &&rhs) noexcept
Move constructor.
IntrusivePointer & operator=(const IntrusivePointer &rhs) noexcept
Assignment operator.
bool operator!=(const T *pRhs) const noexcept
Returns true if the contents of this pointer is not equal to the given pointer.
IntrusivePointer(IntrusivePointer< U > &&rhs) noexcept
Implicit conversion of an r-value to a pointer to a base (or otherwise convertible) type.
void reset()
Reset this pointer to nullptr.
T & operator*() const noexcept
Dereferencing operator.
IntrusivePointer(const IntrusivePointer< T > &rhs) noexcept
Copy constructor.
bool operator!=(const IntrusivePointer< T > &rhs) const noexcept
Returns true if two pointers are not equal.
IntrusivePointer(const IntrusivePointer< U > &rhs) noexcept
Implicit conversion to a pointer to a base (or otherwise convertible) type.
IntrusivePointer & operator=(IntrusivePointer &&rhs) noexcept
Move assignment operator.
T * operator->() const noexcept
Arrow operator.
~IntrusivePointer() noexcept
Default destructor.
IntrusivePointer & operator=(T *p) noexcept
Assignment operator.
IntrusivePointer(T *p=nullptr) noexcept
Default constructor.
bool operator==(const T *pRhs) const noexcept
Returns true if the contents of this pointer is equal to the given pointer.
Utility classes for Cesium.