]>
git.saurik.com Git - apple/xnu.git/blob - libkern/os/smart_ptr.h
1 #ifndef _OS_SMART_POINTER_H
2 #define _OS_SMART_POINTER_H
5 #include <os/cpp_util.h>
7 #pragma clang diagnostic push
8 #pragma clang diagnostic ignored "-Wc++11-extensions"
10 #if __has_attribute(trivial_abi)
11 # define OS_TRIVIAL_ABI __attribute__((trivial_abi))
13 # error Smart pointers depend on trivial_abi attribute
16 #if !OS_HAS_RVALUE_REFERENCES
17 # error Smart pointers depend on rvalue references
20 /* C++98 compatibility */
21 #if !OS_HAS_NULLPTR && !defined(nullptr)
26 # define OSPTR_LOG(x, ...) do {} while(0)
30 static struct no_retain_t
{} no_retain
;
32 template<class T
, class Policy
>
33 class OS_TRIVIAL_ABI smart_ptr
35 template<class U
, class OtherPolicy
> friend class smart_ptr
;
40 * Default constructor, creates a null pointer
42 smart_ptr() : pointer(nullptr)
44 OSPTR_LOG("Default construct smart_ptr\n");
49 * Construction from a nullptr
51 smart_ptr(os::nullptr_t
) : pointer(nullptr)
53 OSPTR_LOG("Construct smart_ptr from null\n");
58 * Construct from a raw pointer, taking a reference to the object
60 explicit smart_ptr(T
*&p
) : pointer(p
)
62 OSPTR_LOG("Construct smart_ptr from raw %p\n", pointer
);
63 if (pointer
!= nullptr) {
69 * Construct from a raw pointer, without bumping the refcount
71 explicit smart_ptr(T
*&p
, no_retain_t
) : pointer(p
)
73 OSPTR_LOG("Construct smart_ptr from raw %p no retain\n", pointer
);
77 * Copy constructor from the same smart_ptr type
79 smart_ptr(smart_ptr
const &rhs
) : pointer(rhs
.pointer
)
81 OSPTR_LOG("Copy construct smart_ptr with %p\n", rhs
.pointer
);
82 if (pointer
!= nullptr) {
87 #if !LIBKERN_NO_MEMBER_TEMPLATES
89 * Allows copy of a smart_ptr<T> from a smart_ptr<U>
90 * if U is convertible to T. For example, if T is a base class of U
93 smart_ptr(smart_ptr
<U
, Policy
> const &rhs
) : pointer(rhs
.get())
95 OSPTR_LOG("Copy construct smart_ptr with compatible %p\n", rhs
.pointer
);
96 if (pointer
!= nullptr) {
103 * Assign to an OSPointer from a raw pointer
108 OSPTR_LOG("Assign smart_ptr with replacing %p with raw %p\n", pointer
, rhs
);
109 smart_ptr(rhs
).swap(*this);
115 * Assign to an OSPointer from a null pointer
118 operator=(os::nullptr_t
)
120 OSPTR_LOG("Assign smart_ptr to null replacing %p\n", pointer
);
121 smart_ptr().swap(*this);
127 * Assign to a smart_ptr from a smart_ptr of the same type
130 operator=(smart_ptr
&rhs
)
132 OSPTR_LOG("Assign smart_ptr replacing %p with %p\n", pointer
, rhs
.pointer
);
133 smart_ptr(rhs
).swap(*this);
137 #if !LIBKERN_NO_MEMBER_TEMPLATES
139 * Allows assignment of a smart_ptr<T> from a smart_ptr<U>
140 * if U is convertible to T. For example, if T is a base class of U.
144 operator=(smart_ptr
<U
, Policy
> const &rhs
)
146 OSPTR_LOG("Assign smart_ptr to compatible replacing %p with %p\n", pointer
, rhs
.pointer
);
147 smart_ptr(rhs
.get()).swap(*this);
156 #if OS_HAS_RVALUE_REFERENCES
158 * Move-construct from a different smart_ptr of the same pointer type
160 smart_ptr(smart_ptr
&&rhs
) : pointer(rhs
.pointer
)
162 OSPTR_LOG("Move construct smart_ptr with %p\n", rhs
.pointer
);
163 rhs
.pointer
= nullptr;
167 * Move-construct from a raw pointer
169 smart_ptr(T
*&&p
) : pointer(p
)
171 OSPTR_LOG("Move construct smart_ptr with %p\n", pointer
);
172 if (pointer
!= nullptr) {
179 * Move-construct from a raw pointer without bumping the refcount
181 smart_ptr(T
*&&p
, no_retain_t
) : pointer(p
)
183 OSPTR_LOG("Move construct smart_ptr with %p no retain\n", pointer
);
188 * Move-assign to a smart_ptr from a raw pointer
193 OSPTR_LOG("Move assign smart_ptr replacing %p with raw %p\n", pointer
, rhs
);
194 smart_ptr(os::move(rhs
)).swap(*this);
200 * Move-assign from a different smart_ptr of the same type
203 operator=(smart_ptr
&&rhs
)
205 OSPTR_LOG("Move assign smart_ptr replacing %p with %p\n", pointer
, rhs
.pointer
);
206 smart_ptr(os::move(rhs
)).swap(*this);
211 * Move from a different smart_ptr with a compatible pointer type
214 smart_ptr(smart_ptr
<U
, Policy
> &&rhs
) : pointer(rhs
.pointer
)
216 OSPTR_LOG("Move construct smart_ptr with compatible %p\n", rhs
.pointer
);
217 rhs
.pointer
= nullptr;
222 operator=(smart_ptr
<U
, Policy
> &&rhs
)
224 OSPTR_LOG("Move assign smart_ptr replacing %p with compatible %p\n", pointer
, rhs
.pointer
);
225 smart_ptr(os::move(rhs
)).swap(*this);
231 * Destructor - decreases the object's reference count
235 OSPTR_LOG("Destroy smart_ptr with %p\n", pointer
);
242 * Create a new object of type T and wrap it in a smart_ptr. The object will have
243 * a reference count of 1, so destruction of the smart_ptr will result in the
244 * object being freed if the smart_ptr wasn't copied first.
246 static inline smart_ptr
249 return smart_ptr(_alloc(), no_retain
);
255 smart_ptr().swap(*this);
272 * Take ownership of object from raw pointer
277 OSPTR_LOG("Attach smart_ptr with %p\n", p
);
278 smart_ptr(p
, no_retain
).swap(*this);
284 OSPTR_LOG("Move attach smart_ptr with %p\n", p
);
285 smart_ptr(os::move(p
), no_retain
).swap(*this);
288 /* Return and drop ownership of pointer with NO release() */
292 OSPTR_LOG("Detach smart_ptr with %p\n", pointer
);
301 OSPTR_LOG("Dereference smart_ptr with %p\n", pointer
);
306 operator bool() const
308 return pointer
!= nullptr;
319 /* swap pointers to the same type but with different policies */
320 template<class OtherPolicy
>
322 swap(smart_ptr
<T
, OtherPolicy
> &p
)
328 smart_ptr
<T
, OtherPolicy
>::_retain(pointer
);
339 smart_ptr
<T
, OtherPolicy
>::_release(pointer
);
345 const_pointer_cast() const &
347 OSPTR_LOG("const_pointer_cast smart_ptr with %p\n", pointer
);
348 return smart_ptr
<U
, Policy
>(const_cast<U
*>(pointer
));
353 const_pointer_cast() &&
355 OSPTR_LOG("const_pointer_cast move smart_ptr with %p\n", pointer
);
356 U
*newPointer
= const_cast<U
*>(detach());
357 return smart_ptr
<U
, Policy
>(os::move(newPointer
), no_retain
);
362 static_pointer_cast() const &
364 OSPTR_LOG("static_pointer_cast smart_ptr with %p\n", pointer
);
365 return smart_ptr
<U
, Policy
>(static_cast<U
*>(pointer
));
370 static_pointer_cast() &&
372 OSPTR_LOG("static_pointer_cast move smart_ptr with %p\n", pointer
);
373 return smart_ptr
<U
, Policy
>(static_cast<U
*>(detach()), no_retain
);
378 dynamic_pointer_cast() const &
380 OSPTR_LOG("dynamic_pointer_cast smart_ptr with %p\n", pointer
);
381 return smart_ptr
<U
, Policy
>(Policy::template dyn_cast
<T
, U
>(pointer
));
386 dynamic_pointer_cast() &&
388 OSPTR_LOG("dynamic_pointer_cast move smart_ptr with %p\n", pointer
);
389 U
*newPointer
= Policy::template dyn_cast
<T
, U
>(pointer
);
391 if (newPointer
!= nullptr) {
396 return smart_ptr
<U
, Policy
>(os::move(newPointer
), no_retain
);
403 OSPTR_LOG(" %s with %p\n", __FUNCTION__
, obj
);
410 OSPTR_LOG(" %s with %p\n", __FUNCTION__
, obj
);
411 Policy::release(obj
);
417 OSPTR_LOG(" %s\n", __FUNCTION__
);
418 return Policy::template alloc
<T
>();
428 template<class T
, class Policy
>
430 operator==(smart_ptr
<T
, Policy
> const &a
, smart_ptr
<T
, Policy
> const &b
)
432 return a
.get() == b
.get();
435 template<class T
, class Policy
>
437 operator!=(smart_ptr
<T
, Policy
> const &a
, smart_ptr
<T
, Policy
> const &b
)
439 return a
.get() != b
.get();
442 template<class A
, class A_policy
, class B
, class B_policy
>
444 operator==(smart_ptr
<A
, A_policy
> const &a
, smart_ptr
<B
, B_policy
> const &b
)
446 return a
.get() == b
.get();
449 template<class A
, class A_policy
, class B
, class B_policy
>
451 operator!=(smart_ptr
<A
, A_policy
> const &a
, smart_ptr
<B
, B_policy
> const &b
)
453 return a
.get() != b
.get();
457 * Comparison with nullptr
461 template<class T
, class Policy
>
463 operator==(smart_ptr
<T
, Policy
> const &p
, os::nullptr_t
)
465 return p
.get() == nullptr;
468 template<class T
, class Policy
> inline bool
469 operator==(os::nullptr_t
, smart_ptr
<T
, Policy
> const &p
)
471 return p
.get() == nullptr;
474 template<class T
, class Policy
>
476 operator!=(smart_ptr
<T
, Policy
> const &p
, os::nullptr_t
)
478 return p
.get() != nullptr;
481 template<class T
, class Policy
>
483 operator!=(os::nullptr_t
, smart_ptr
<T
, Policy
> const &p
)
485 return p
.get() != nullptr;
490 * Comparison with raw pointer
493 template<class T
, class Policy
>
495 operator==(smart_ptr
<T
, Policy
> const &p
, const os::remove_const_t
<T
> *other
)
497 return p
.get() == other
;
500 template<class T
, class Policy
>
502 operator==(const os::remove_const_t
<T
> *other
, smart_ptr
<T
, Policy
> const &p
)
504 return other
== p
.get();
507 template<class T
, class Policy
>
509 operator!=(smart_ptr
<T
, Policy
> const &p
, const os::remove_const_t
<T
> *other
)
511 return p
.get() != other
;
514 template<class T
, class Policy
>
516 operator!=(const os::remove_const_t
<T
> *other
, smart_ptr
<T
, Policy
> const &p
)
518 return other
!= p
.get();
522 #pragma clang diagnostic pop
523 #endif /* _OS_SMART_POINTER_H */