cesium-native 0.47.0
Loading...
Searching...
No Matches
IntrusivePointer.h
1#pragma once
2
3#include <functional>
4#include <type_traits>
5#include <utility>
6
7namespace CesiumUtility {
8
21template <class T> class IntrusivePointer final {
22public:
26 IntrusivePointer(T* p = nullptr) noexcept : _p(p) { this->addReference(); }
27
31 IntrusivePointer(const IntrusivePointer<T>& rhs) noexcept : _p(rhs._p) {
32 this->addReference();
33 }
34
42 template <class U>
43 IntrusivePointer(const IntrusivePointer<U>& rhs) noexcept : _p(rhs._p) {
44 this->addReference();
45 }
46
51 : _p(std::exchange(rhs._p, nullptr)) {
52 // Reference count is unchanged
53 }
54
62 template <class U>
64 : _p(std::exchange(rhs._p, nullptr)) {
65 // Reference count is unchanged
66 }
67
71 ~IntrusivePointer() noexcept { this->releaseReference(); }
72
82 template <typename... ConstructorArgumentTypes>
83 T& emplace(ConstructorArgumentTypes&&... constructorArguments) {
84 *this =
85 new T(std::forward<ConstructorArgumentTypes>(constructorArguments)...);
86 return *this->get();
87 }
88
92 void reset() { *this = nullptr; }
93
97 // NOLINTNEXTLINE(bugprone-unhandled-self-assignment)
99 if (*this != rhs) {
100 // addReference the new pointer before releaseReference'ing the old.
101 T* pOld = this->_p;
102 this->_p = rhs._p;
103 addReference();
104
105 if (pOld) {
106 pOld->releaseReference();
107 }
108 }
109
110 return *this;
111 }
112
117 template <class U>
119 if (*this != rhs) {
120 // addReference the new pointer before releaseReference'ing the old.
121 T* pOld = this->_p;
122 this->_p = rhs._p;
123 addReference();
124
125 if (pOld) {
126 pOld->releaseReference();
127 }
128 }
129
130 return *this;
131 }
132
137 if (this->_p != rhs._p) {
138 std::swap(this->_p, rhs._p);
139 }
140
141 return *this;
142 }
143
147 IntrusivePointer& operator=(T* p) noexcept {
148 if (this->_p != p) {
149 // addReference the new pointer before releaseReference'ing the old.
150 T* pOld = this->_p;
151 this->_p = p;
152 addReference();
153
154 if (pOld) {
155 pOld->releaseReference();
156 }
157 }
158
159 return *this;
160 }
161
165 T& operator*() const noexcept { return *this->_p; }
166
170 T* operator->() const noexcept { return this->_p; }
171
176 explicit operator bool() const noexcept { return this->_p != nullptr; }
177
181 T* get() const noexcept { return this->_p; }
182
186 bool operator==(const IntrusivePointer<T>& rhs) const noexcept {
187 return this->_p == rhs._p;
188 }
189
191 template <class U>
192 bool operator==(const IntrusivePointer<U>& rhs) const noexcept {
193 return this->_p == rhs._p;
194 }
195
199 bool operator!=(const IntrusivePointer<T>& rhs) const noexcept {
200 return !(*this == rhs);
201 }
202
206 template <class U>
207 bool operator!=(const IntrusivePointer<U>& rhs) const noexcept {
208 return !(*this == rhs);
209 }
210
215 bool operator==(const T* pRhs) const noexcept { return this->_p == pRhs; }
216
221 bool operator!=(const T* pRhs) const noexcept { return !(*this == pRhs); }
222
223private:
224 void addReference() noexcept {
225 if (this->_p) {
226 this->_p->addReference();
227 }
228 }
229
230 void releaseReference() noexcept {
231 if (this->_p) {
232 this->_p->releaseReference();
233 }
234 }
235
236 T* _p;
237 template <typename U> friend class IntrusivePointer;
238};
239
246template <typename T, typename U>
247IntrusivePointer<T>
249 return IntrusivePointer<T>(const_cast<T*>(p.get()));
250}
251
252} // namespace CesiumUtility
253
255template <typename T> struct std::hash<CesiumUtility::IntrusivePointer<T>> {
258 std::size_t
260 std::hash<T*> hasher{};
261 return hasher(key.get());
262 }
263};
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 * operator->() const noexcept
Arrow operator.
bool operator==(const IntrusivePointer< U > &rhs) const noexcept
Returns true if two pointers are equal.
IntrusivePointer & operator=(const IntrusivePointer &rhs) noexcept
Assignment operator.
IntrusivePointer(IntrusivePointer< T > &&rhs) noexcept
Move constructor.
IntrusivePointer & operator=(IntrusivePointer &&rhs) noexcept
Move assignment operator.
bool operator!=(const T *pRhs) const noexcept
Returns true if the contents of this pointer is not equal to the given pointer.
T & operator*() const noexcept
Dereferencing operator.
IntrusivePointer(IntrusivePointer< U > &&rhs) noexcept
Implicit conversion of an r-value to a pointer to a base (or otherwise convertible) type.
bool operator!=(const IntrusivePointer< U > &rhs) const noexcept
Returns true if two pointers are not equal.
void reset()
Reset this pointer to nullptr.
IntrusivePointer & operator=(const IntrusivePointer< U > &rhs) noexcept
Assigns an IntrusivePointer of another type to this IntrusivePointer.
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=(T *p) noexcept
Assignment operator.
~IntrusivePointer() noexcept
Default destructor.
IntrusivePointer(T *p=nullptr) noexcept
Default constructor.
T * get() const noexcept
Returns the internal pointer.
T & emplace(ConstructorArgumentTypes &&... constructorArguments)
Constructs a new instance and assigns it to this IntrusivePointer. If this IntrusivePointer already p...
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.
IntrusivePointer< T > const_intrusive_cast(const IntrusivePointer< U > &p) noexcept
Casts a const IntrusivePointer to its non-const equivalent.
std::size_t operator()(const CesiumUtility::IntrusivePointer< T > &key) const noexcept
Returns a size_t hash of the provided CesiumUtility::IntrusivePointer<T>.