Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/metal-cpp/Foundation/NSSharedPtr.hpp
21066 views
1
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
2
//
3
// Foundation/NSSharedPtr.hpp
4
//
5
// Copyright 2020-2024 Apple Inc.
6
//
7
// Licensed under the Apache License, Version 2.0 (the "License");
8
// you may not use this file except in compliance with the License.
9
// You may obtain a copy of the License at
10
//
11
// http://www.apache.org/licenses/LICENSE-2.0
12
//
13
// Unless required by applicable law or agreed to in writing, software
14
// distributed under the License is distributed on an "AS IS" BASIS,
15
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
// See the License for the specific language governing permissions and
17
// limitations under the License.
18
//
19
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
20
21
#pragma once
22
23
#include <cstddef>
24
#include "NSDefines.hpp"
25
26
namespace NS
27
{
28
template <class _Class>
29
class SharedPtr
30
{
31
public:
32
/**
33
* Create a new null pointer.
34
*/
35
SharedPtr();
36
37
/**
38
* Destroy this SharedPtr, decreasing the reference count.
39
*/
40
~SharedPtr();
41
42
/**
43
* Create a new null pointer.
44
*/
45
SharedPtr(std::nullptr_t) noexcept;
46
47
/**
48
* SharedPtr copy constructor.
49
*/
50
SharedPtr(const SharedPtr<_Class>& other) noexcept;
51
52
/**
53
* Construction from another pointee type.
54
*/
55
template <class _OtherClass>
56
SharedPtr(const SharedPtr<_OtherClass>& other, typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>> * = nullptr) noexcept;
57
58
/**
59
* SharedPtr move constructor.
60
*/
61
SharedPtr(SharedPtr<_Class>&& other) noexcept;
62
63
/**
64
* Move from another pointee type.
65
*/
66
template <class _OtherClass>
67
SharedPtr(SharedPtr<_OtherClass>&& other, typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>> * = nullptr) noexcept;
68
69
/**
70
* Copy assignment operator.
71
* Copying increases reference count. Only releases previous pointee if objects are different.
72
*/
73
SharedPtr& operator=(const SharedPtr<_Class>& other);
74
75
/**
76
* Copy-assignment from different pointee.
77
* Copying increases reference count. Only releases previous pointee if objects are different.
78
*/
79
template <class _OtherClass>
80
typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>, SharedPtr &>
81
operator=(const SharedPtr<_OtherClass>& other);
82
83
/**
84
* Move assignment operator.
85
* Move without affecting reference counts, unless pointees are equal. Moved-from object is reset to nullptr.
86
*/
87
SharedPtr& operator=(SharedPtr<_Class>&& other);
88
89
/**
90
* Move-asignment from different pointee.
91
* Move without affecting reference counts, unless pointees are equal. Moved-from object is reset to nullptr.
92
*/
93
template <class _OtherClass>
94
typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>, SharedPtr &>
95
operator=(SharedPtr<_OtherClass>&& other);
96
97
/**
98
* Access raw pointee.
99
* @warning Avoid wrapping the returned value again, as it may lead double frees unless this object becomes detached.
100
*/
101
_Class* get() const;
102
103
/**
104
* Call operations directly on the pointee.
105
*/
106
_Class* operator->() const;
107
108
/**
109
* Implicit cast to bool.
110
*/
111
explicit operator bool() const;
112
113
/**
114
* Reset this SharedPtr to null, decreasing the reference count.
115
*/
116
void reset();
117
118
/**
119
* Detach the SharedPtr from the pointee, without decreasing the reference count.
120
*/
121
void detach();
122
123
template <class _OtherClass>
124
friend SharedPtr<_OtherClass> RetainPtr(_OtherClass* ptr);
125
126
template <class _OtherClass>
127
friend SharedPtr<_OtherClass> TransferPtr(_OtherClass* ptr);
128
129
private:
130
_Class* m_pObject;
131
};
132
133
/**
134
* Create a SharedPtr by retaining an existing raw pointer.
135
* Increases the reference count of the passed-in object.
136
* If the passed-in object was in an AutoreleasePool, it will be removed from it.
137
*/
138
template <class _Class>
139
_NS_INLINE NS::SharedPtr<_Class> RetainPtr(_Class* pObject)
140
{
141
NS::SharedPtr<_Class> ret;
142
ret.m_pObject = pObject->retain();
143
return ret;
144
}
145
146
/*
147
* Create a SharedPtr by transfering the ownership of an existing raw pointer to SharedPtr.
148
* Does not increase the reference count of the passed-in pointer, it is assumed to be >= 1.
149
* This method does not remove objects from an AutoreleasePool.
150
*/
151
template <class _Class>
152
_NS_INLINE NS::SharedPtr<_Class> TransferPtr(_Class* pObject)
153
{
154
NS::SharedPtr<_Class> ret;
155
ret.m_pObject = pObject;
156
return ret;
157
}
158
159
}
160
161
template <class _Class>
162
_NS_INLINE NS::SharedPtr<_Class>::SharedPtr()
163
: m_pObject(nullptr)
164
{
165
}
166
167
template <class _Class>
168
_NS_INLINE NS::SharedPtr<_Class>::~SharedPtr<_Class>() __attribute__((no_sanitize("undefined")))
169
{
170
m_pObject->release();
171
}
172
173
template <class _Class>
174
_NS_INLINE NS::SharedPtr<_Class>::SharedPtr(std::nullptr_t) noexcept
175
: m_pObject(nullptr)
176
{
177
}
178
179
template <class _Class>
180
_NS_INLINE NS::SharedPtr<_Class>::SharedPtr(const SharedPtr<_Class>& other) noexcept
181
: m_pObject(other.m_pObject->retain())
182
{
183
}
184
185
template <class _Class>
186
template <class _OtherClass>
187
_NS_INLINE NS::SharedPtr<_Class>::SharedPtr(const SharedPtr<_OtherClass>& other, typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>> *) noexcept
188
: m_pObject(reinterpret_cast<_Class*>(other.get()->retain()))
189
{
190
}
191
192
template <class _Class>
193
_NS_INLINE NS::SharedPtr<_Class>::SharedPtr(SharedPtr<_Class>&& other) noexcept
194
: m_pObject(other.m_pObject)
195
{
196
other.m_pObject = nullptr;
197
}
198
199
template <class _Class>
200
template <class _OtherClass>
201
_NS_INLINE NS::SharedPtr<_Class>::SharedPtr(SharedPtr<_OtherClass>&& other, typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>> *) noexcept
202
: m_pObject(reinterpret_cast<_Class*>(other.get()))
203
{
204
other.detach();
205
}
206
207
template <class _Class>
208
_NS_INLINE _Class* NS::SharedPtr<_Class>::get() const
209
{
210
return m_pObject;
211
}
212
213
template <class _Class>
214
_NS_INLINE _Class* NS::SharedPtr<_Class>::operator->() const
215
{
216
return m_pObject;
217
}
218
219
template <class _Class>
220
_NS_INLINE NS::SharedPtr<_Class>::operator bool() const
221
{
222
return nullptr != m_pObject;
223
}
224
225
template <class _Class>
226
_NS_INLINE void NS::SharedPtr<_Class>::reset() __attribute__((no_sanitize("undefined")))
227
{
228
m_pObject->release();
229
m_pObject = nullptr;
230
}
231
232
template <class _Class>
233
_NS_INLINE void NS::SharedPtr<_Class>::detach()
234
{
235
m_pObject = nullptr;
236
}
237
238
template <class _Class>
239
_NS_INLINE NS::SharedPtr<_Class>& NS::SharedPtr<_Class>::operator=(const SharedPtr<_Class>& other) __attribute__((no_sanitize("undefined")))
240
{
241
_Class* pOldObject = m_pObject;
242
243
m_pObject = other.m_pObject->retain();
244
245
pOldObject->release();
246
247
return *this;
248
}
249
250
template <class _Class>
251
template <class _OtherClass>
252
typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>, NS::SharedPtr<_Class> &>
253
_NS_INLINE NS::SharedPtr<_Class>::operator=(const SharedPtr<_OtherClass>& other) __attribute__((no_sanitize("undefined")))
254
{
255
_Class* pOldObject = m_pObject;
256
257
m_pObject = reinterpret_cast<_Class*>(other.get()->retain());
258
259
pOldObject->release();
260
261
return *this;
262
}
263
264
template <class _Class>
265
_NS_INLINE NS::SharedPtr<_Class>& NS::SharedPtr<_Class>::operator=(SharedPtr<_Class>&& other) __attribute__((no_sanitize("undefined")))
266
{
267
if (m_pObject != other.m_pObject)
268
{
269
m_pObject->release();
270
m_pObject = other.m_pObject;
271
}
272
else
273
{
274
m_pObject = other.m_pObject;
275
other.m_pObject->release();
276
}
277
other.m_pObject = nullptr;
278
return *this;
279
}
280
281
template <class _Class>
282
template <class _OtherClass>
283
typename std::enable_if_t<std::is_convertible_v<_OtherClass *, _Class *>, NS::SharedPtr<_Class> &>
284
_NS_INLINE NS::SharedPtr<_Class>::operator=(SharedPtr<_OtherClass>&& other) __attribute__((no_sanitize("undefined")))
285
{
286
if (m_pObject != other.get())
287
{
288
m_pObject->release();
289
m_pObject = reinterpret_cast<_Class*>(other.get());
290
other.detach();
291
}
292
else
293
{
294
m_pObject = other.get();
295
other.reset();
296
}
297
return *this;
298
}
299
300
template <class _ClassLhs, class _ClassRhs>
301
_NS_INLINE bool operator==(const NS::SharedPtr<_ClassLhs>& lhs, const NS::SharedPtr<_ClassRhs>& rhs)
302
{
303
return lhs.get() == rhs.get();
304
}
305
306
template <class _ClassLhs, class _ClassRhs>
307
_NS_INLINE bool operator!=(const NS::SharedPtr<_ClassLhs>& lhs, const NS::SharedPtr<_ClassRhs>& rhs)
308
{
309
return lhs.get() != rhs.get();
310
}
311
312