cesium-native 0.51.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 <typename T> class IntrusivePointer final {
22public:
26 using element_type = T;
27
31 IntrusivePointer(T* p = nullptr) noexcept : _p(p) { this->addReference(); }
32
36 IntrusivePointer(const IntrusivePointer<T>& rhs) noexcept : _p(rhs._p) {
37 this->addReference();
38 }
39
47 template <class U>
48 IntrusivePointer(const IntrusivePointer<U>& rhs) noexcept : _p(rhs._p) {
49 this->addReference();
50 }
51
55 IntrusivePointer(IntrusivePointer<T>&& rhs) noexcept
56 : _p(std::exchange(rhs._p, nullptr)) {
57 // Reference count is unchanged
58 }
59
67 template <class U>
68 IntrusivePointer(IntrusivePointer<U>&& rhs) noexcept
69 : _p(std::exchange(rhs._p, nullptr)) {
70 // Reference count is unchanged
71 }
72
76 ~IntrusivePointer() noexcept { this->releaseReference(); }
77
81 operator T*() noexcept { return this->_p; }
82
86 operator const T*() const noexcept { return this->_p; }
87
97 template <typename... ConstructorArgumentTypes>
98 T& emplace(ConstructorArgumentTypes&&... constructorArguments) {
99 *this =
100 new T(std::forward<ConstructorArgumentTypes>(constructorArguments)...);
101 return *this->get();
102 }
103
107 void reset() { *this = nullptr; }
108
112 // NOLINTNEXTLINE(bugprone-unhandled-self-assignment)
113 IntrusivePointer& operator=(const IntrusivePointer& rhs) noexcept {
114 if (*this != rhs) {
115 // addReference the new pointer before releaseReference'ing the old.
116 T* pOld = this->_p;
117 this->_p = rhs._p;
118 addReference();
119
120 if (pOld) {
121 pOld->releaseReference();
122 }
123 }
124
125 return *this;
126 }
127
132 template <class U>
133 IntrusivePointer& operator=(const IntrusivePointer<U>& rhs) noexcept {
134 if (*this != rhs) {
135 // addReference the new pointer before releaseReference'ing the old.
136 T* pOld = this->_p;
137 this->_p = rhs._p;
138 addReference();
139
140 if (pOld) {
141 pOld->releaseReference();
142 }
143 }
144
145 return *this;
146 }
147
151 IntrusivePointer& operator=(IntrusivePointer&& rhs) noexcept {
152 if (this->_p != rhs._p) {
153 std::swap(this->_p, rhs._p);
154 }
155
156 return *this;
157 }
158
162 IntrusivePointer& operator=(T* p) noexcept {
163 if (this->_p != p) {
164 // addReference the new pointer before releaseReference'ing the old.
165 T* pOld = this->_p;
166 this->_p = p;
167 addReference();
168
169 if (pOld) {
170 pOld->releaseReference();
171 }
172 }
173
174 return *this;
175 }
176
180 T& operator*() const noexcept { return *this->_p; }
181
185 T* operator->() const noexcept { return this->_p; }
186
191 explicit operator bool() const noexcept { return this->_p != nullptr; }
192
197 explicit operator bool() noexcept { return this->_p != nullptr; }
198
202 T* get() const noexcept { return this->_p; }
203
207 bool operator==(const IntrusivePointer<T>& rhs) const noexcept {
208 return this->_p == rhs._p;
209 }
210
212 template <class U>
213 bool operator==(const IntrusivePointer<U>& rhs) const noexcept {
214 return this->_p == rhs._p;
215 }
216
220 bool operator!=(const IntrusivePointer<T>& rhs) const noexcept {
221 return !(*this == rhs);
222 }
223
227 template <class U>
228 bool operator!=(const IntrusivePointer<U>& rhs) const noexcept {
229 return !(*this == rhs);
230 }
231
236 bool operator==(const T* pRhs) const noexcept { return this->_p == pRhs; }
237
242 bool operator!=(const T* pRhs) const noexcept { return !(*this == pRhs); }
243
244private:
245 void addReference() noexcept {
246 if (this->_p) {
247 this->_p->addReference();
248 }
249 }
250
251 void releaseReference() noexcept {
252 if (this->_p) {
253 this->_p->releaseReference();
254 }
255 }
256
257 T* _p;
258 template <typename U> friend class IntrusivePointer;
259};
260
267template <typename T, typename U>
270 return IntrusivePointer<T>(const_cast<T*>(p.get()));
271}
272
273} // namespace CesiumUtility
274
276template <typename T> struct std::hash<CesiumUtility::IntrusivePointer<T>> {
279 std::size_t
281 std::hash<T*> hasher{};
282 return hasher(key.get());
283 }
284};
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>.