1fe6060f1SDimitry Andric // -*- C++ -*- 2fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 3fe6060f1SDimitry Andric // 4fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7fe6060f1SDimitry Andric // 8fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 9fe6060f1SDimitry Andric 10fe6060f1SDimitry Andric #ifndef _LIBCPP___MEMORY_SHARED_PTR_H 11fe6060f1SDimitry Andric #define _LIBCPP___MEMORY_SHARED_PTR_H 12fe6060f1SDimitry Andric 13bdd1243dSDimitry Andric #include <__compare/compare_three_way.h> 14bdd1243dSDimitry Andric #include <__compare/ordering.h> 15fe6060f1SDimitry Andric #include <__config> 165f757f3fSDimitry Andric #include <__exception/exception.h> 17fe6060f1SDimitry Andric #include <__functional/binary_function.h> 18fe6060f1SDimitry Andric #include <__functional/operations.h> 19fe6060f1SDimitry Andric #include <__functional/reference_wrapper.h> 205f757f3fSDimitry Andric #include <__fwd/ostream.h> 2181ad6265SDimitry Andric #include <__iterator/access.h> 22fe6060f1SDimitry Andric #include <__memory/addressof.h> 23fe6060f1SDimitry Andric #include <__memory/allocation_guard.h> 24fe6060f1SDimitry Andric #include <__memory/allocator.h> 25bdd1243dSDimitry Andric #include <__memory/allocator_destructor.h> 2604eeddc0SDimitry Andric #include <__memory/allocator_traits.h> 2781ad6265SDimitry Andric #include <__memory/auto_ptr.h> 28fe6060f1SDimitry Andric #include <__memory/compressed_pair.h> 2981ad6265SDimitry Andric #include <__memory/construct_at.h> 30fe6060f1SDimitry Andric #include <__memory/pointer_traits.h> 3181ad6265SDimitry Andric #include <__memory/uninitialized_algorithms.h> 32fe6060f1SDimitry Andric #include <__memory/unique_ptr.h> 3306c3fb27SDimitry Andric #include <__type_traits/add_lvalue_reference.h> 3406c3fb27SDimitry Andric #include <__type_traits/conditional.h> 3506c3fb27SDimitry Andric #include <__type_traits/conjunction.h> 3606c3fb27SDimitry Andric #include <__type_traits/disjunction.h> 3706c3fb27SDimitry Andric #include <__type_traits/is_array.h> 3806c3fb27SDimitry Andric #include <__type_traits/is_bounded_array.h> 39*0fca6ea1SDimitry Andric #include <__type_traits/is_constructible.h> 4006c3fb27SDimitry Andric #include <__type_traits/is_convertible.h> 4106c3fb27SDimitry Andric #include <__type_traits/is_reference.h> 4206c3fb27SDimitry Andric #include <__type_traits/is_unbounded_array.h> 4306c3fb27SDimitry Andric #include <__type_traits/nat.h> 4406c3fb27SDimitry Andric #include <__type_traits/negation.h> 4506c3fb27SDimitry Andric #include <__type_traits/remove_extent.h> 4606c3fb27SDimitry Andric #include <__type_traits/remove_reference.h> 4706c3fb27SDimitry Andric #include <__utility/declval.h> 48fe6060f1SDimitry Andric #include <__utility/forward.h> 4981ad6265SDimitry Andric #include <__utility/move.h> 5081ad6265SDimitry Andric #include <__utility/swap.h> 5106c3fb27SDimitry Andric #include <__verbose_abort> 52fe6060f1SDimitry Andric #include <cstddef> 53bdd1243dSDimitry Andric #include <new> 5404eeddc0SDimitry Andric #include <typeinfo> 55fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) 5606c3fb27SDimitry Andric # include <__atomic/memory_order.h> 57fe6060f1SDimitry Andric #endif 58fe6060f1SDimitry Andric 59fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 60fe6060f1SDimitry Andric # pragma GCC system_header 61fe6060f1SDimitry Andric #endif 62fe6060f1SDimitry Andric 63b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS 64b3edf446SDimitry Andric #include <__undef_macros> 65b3edf446SDimitry Andric 66fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 67fe6060f1SDimitry Andric 68fe6060f1SDimitry Andric // NOTE: Relaxed and acq/rel atomics (for increment and decrement respectively) 69fe6060f1SDimitry Andric // should be sufficient for thread safety. 70fe6060f1SDimitry Andric // See https://llvm.org/PR22803 71cb14a3feSDimitry Andric #if defined(__clang__) && __has_builtin(__atomic_add_fetch) && defined(__ATOMIC_RELAXED) && defined(__ATOMIC_ACQ_REL) 72fe6060f1SDimitry Andric # define _LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT 73fe6060f1SDimitry Andric #elif defined(_LIBCPP_COMPILER_GCC) 74fe6060f1SDimitry Andric # define _LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT 75fe6060f1SDimitry Andric #endif 76fe6060f1SDimitry Andric 77fe6060f1SDimitry Andric template <class _ValueType> 78cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_relaxed_load(_ValueType const* __value) { 79cb14a3feSDimitry Andric #if !defined(_LIBCPP_HAS_NO_THREADS) && defined(__ATOMIC_RELAXED) && \ 80fe6060f1SDimitry Andric (__has_builtin(__atomic_load_n) || defined(_LIBCPP_COMPILER_GCC)) 81fe6060f1SDimitry Andric return __atomic_load_n(__value, __ATOMIC_RELAXED); 82fe6060f1SDimitry Andric #else 83fe6060f1SDimitry Andric return *__value; 84fe6060f1SDimitry Andric #endif 85fe6060f1SDimitry Andric } 86fe6060f1SDimitry Andric 87fe6060f1SDimitry Andric template <class _ValueType> 88cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_acquire_load(_ValueType const* __value) { 89cb14a3feSDimitry Andric #if !defined(_LIBCPP_HAS_NO_THREADS) && defined(__ATOMIC_ACQUIRE) && \ 90fe6060f1SDimitry Andric (__has_builtin(__atomic_load_n) || defined(_LIBCPP_COMPILER_GCC)) 91fe6060f1SDimitry Andric return __atomic_load_n(__value, __ATOMIC_ACQUIRE); 92fe6060f1SDimitry Andric #else 93fe6060f1SDimitry Andric return *__value; 94fe6060f1SDimitry Andric #endif 95fe6060f1SDimitry Andric } 96fe6060f1SDimitry Andric 97fe6060f1SDimitry Andric template <class _Tp> 98cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _Tp __libcpp_atomic_refcount_increment(_Tp& __t) _NOEXCEPT { 99fe6060f1SDimitry Andric #if defined(_LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT) && !defined(_LIBCPP_HAS_NO_THREADS) 100fe6060f1SDimitry Andric return __atomic_add_fetch(&__t, 1, __ATOMIC_RELAXED); 101fe6060f1SDimitry Andric #else 102fe6060f1SDimitry Andric return __t += 1; 103fe6060f1SDimitry Andric #endif 104fe6060f1SDimitry Andric } 105fe6060f1SDimitry Andric 106fe6060f1SDimitry Andric template <class _Tp> 107cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _Tp __libcpp_atomic_refcount_decrement(_Tp& __t) _NOEXCEPT { 108fe6060f1SDimitry Andric #if defined(_LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT) && !defined(_LIBCPP_HAS_NO_THREADS) 109fe6060f1SDimitry Andric return __atomic_add_fetch(&__t, -1, __ATOMIC_ACQ_REL); 110fe6060f1SDimitry Andric #else 111fe6060f1SDimitry Andric return __t -= 1; 112fe6060f1SDimitry Andric #endif 113fe6060f1SDimitry Andric } 114fe6060f1SDimitry Andric 115cb14a3feSDimitry Andric class _LIBCPP_EXPORTED_FROM_ABI bad_weak_ptr : public std::exception { 116fe6060f1SDimitry Andric public: 11706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI bad_weak_ptr() _NOEXCEPT = default; 11806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI bad_weak_ptr(const bad_weak_ptr&) _NOEXCEPT = default; 1195f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI bad_weak_ptr& operator=(const bad_weak_ptr&) _NOEXCEPT = default; 120bdd1243dSDimitry Andric ~bad_weak_ptr() _NOEXCEPT override; 121bdd1243dSDimitry Andric const char* what() const _NOEXCEPT override; 122fe6060f1SDimitry Andric }; 123fe6060f1SDimitry Andric 124cb14a3feSDimitry Andric _LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI void __throw_bad_weak_ptr() { 12506c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 126fe6060f1SDimitry Andric throw bad_weak_ptr(); 127fe6060f1SDimitry Andric #else 12806c3fb27SDimitry Andric _LIBCPP_VERBOSE_ABORT("bad_weak_ptr was thrown in -fno-exceptions mode"); 129fe6060f1SDimitry Andric #endif 130fe6060f1SDimitry Andric } 131fe6060f1SDimitry Andric 132cb14a3feSDimitry Andric template <class _Tp> 133cb14a3feSDimitry Andric class _LIBCPP_TEMPLATE_VIS weak_ptr; 134fe6060f1SDimitry Andric 135cb14a3feSDimitry Andric class _LIBCPP_EXPORTED_FROM_ABI __shared_count { 136fe6060f1SDimitry Andric __shared_count(const __shared_count&); 137fe6060f1SDimitry Andric __shared_count& operator=(const __shared_count&); 138fe6060f1SDimitry Andric 139fe6060f1SDimitry Andric protected: 140fe6060f1SDimitry Andric long __shared_owners_; 141fe6060f1SDimitry Andric virtual ~__shared_count(); 142cb14a3feSDimitry Andric 143fe6060f1SDimitry Andric private: 144fe6060f1SDimitry Andric virtual void __on_zero_shared() _NOEXCEPT = 0; 145fe6060f1SDimitry Andric 146fe6060f1SDimitry Andric public: 147cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __shared_count(long __refs = 0) _NOEXCEPT : __shared_owners_(__refs) {} 148fe6060f1SDimitry Andric 14981ad6265SDimitry Andric #if defined(_LIBCPP_SHARED_PTR_DEFINE_LEGACY_INLINE_FUNCTIONS) 15081ad6265SDimitry Andric void __add_shared() noexcept; 15181ad6265SDimitry Andric bool __release_shared() noexcept; 152fe6060f1SDimitry Andric #else 153cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __add_shared() _NOEXCEPT { __libcpp_atomic_refcount_increment(__shared_owners_); } 154cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __release_shared() _NOEXCEPT { 155fe6060f1SDimitry Andric if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1) { 156fe6060f1SDimitry Andric __on_zero_shared(); 157fe6060f1SDimitry Andric return true; 158fe6060f1SDimitry Andric } 159fe6060f1SDimitry Andric return false; 160fe6060f1SDimitry Andric } 161fe6060f1SDimitry Andric #endif 162cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI long use_count() const _NOEXCEPT { return __libcpp_relaxed_load(&__shared_owners_) + 1; } 163fe6060f1SDimitry Andric }; 164fe6060f1SDimitry Andric 165cb14a3feSDimitry Andric class _LIBCPP_EXPORTED_FROM_ABI __shared_weak_count : private __shared_count { 166fe6060f1SDimitry Andric long __shared_weak_owners_; 167fe6060f1SDimitry Andric 168fe6060f1SDimitry Andric public: 169cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __shared_weak_count(long __refs = 0) _NOEXCEPT 170fe6060f1SDimitry Andric : __shared_count(__refs), 171fe6060f1SDimitry Andric __shared_weak_owners_(__refs) {} 172cb14a3feSDimitry Andric 173fe6060f1SDimitry Andric protected: 174bdd1243dSDimitry Andric ~__shared_weak_count() override; 175fe6060f1SDimitry Andric 176fe6060f1SDimitry Andric public: 17781ad6265SDimitry Andric #if defined(_LIBCPP_SHARED_PTR_DEFINE_LEGACY_INLINE_FUNCTIONS) 17881ad6265SDimitry Andric void __add_shared() noexcept; 17981ad6265SDimitry Andric void __add_weak() noexcept; 18081ad6265SDimitry Andric void __release_shared() noexcept; 181fe6060f1SDimitry Andric #else 182cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __add_shared() _NOEXCEPT { __shared_count::__add_shared(); } 183cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __add_weak() _NOEXCEPT { __libcpp_atomic_refcount_increment(__shared_weak_owners_); } 184cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __release_shared() _NOEXCEPT { 185fe6060f1SDimitry Andric if (__shared_count::__release_shared()) 186fe6060f1SDimitry Andric __release_weak(); 187fe6060f1SDimitry Andric } 188fe6060f1SDimitry Andric #endif 189fe6060f1SDimitry Andric void __release_weak() _NOEXCEPT; 190cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI long use_count() const _NOEXCEPT { return __shared_count::use_count(); } 191fe6060f1SDimitry Andric __shared_weak_count* lock() _NOEXCEPT; 192fe6060f1SDimitry Andric 193fe6060f1SDimitry Andric virtual const void* __get_deleter(const type_info&) const _NOEXCEPT; 194cb14a3feSDimitry Andric 195fe6060f1SDimitry Andric private: 196fe6060f1SDimitry Andric virtual void __on_zero_shared_weak() _NOEXCEPT = 0; 197fe6060f1SDimitry Andric }; 198fe6060f1SDimitry Andric 199fe6060f1SDimitry Andric template <class _Tp, class _Dp, class _Alloc> 200cb14a3feSDimitry Andric class __shared_ptr_pointer : public __shared_weak_count { 201fe6060f1SDimitry Andric __compressed_pair<__compressed_pair<_Tp, _Dp>, _Alloc> __data_; 202cb14a3feSDimitry Andric 203fe6060f1SDimitry Andric public: 204cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __shared_ptr_pointer(_Tp __p, _Dp __d, _Alloc __a) 2055f757f3fSDimitry Andric : __data_(__compressed_pair<_Tp, _Dp>(__p, std::move(__d)), std::move(__a)) {} 206fe6060f1SDimitry Andric 2071ac55f4cSDimitry Andric #ifndef _LIBCPP_HAS_NO_RTTI 20806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI_VIRTUAL const void* __get_deleter(const type_info&) const _NOEXCEPT override; 209fe6060f1SDimitry Andric #endif 210fe6060f1SDimitry Andric 211fe6060f1SDimitry Andric private: 21206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override; 21306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override; 214fe6060f1SDimitry Andric }; 215fe6060f1SDimitry Andric 2161ac55f4cSDimitry Andric #ifndef _LIBCPP_HAS_NO_RTTI 217fe6060f1SDimitry Andric 218fe6060f1SDimitry Andric template <class _Tp, class _Dp, class _Alloc> 219cb14a3feSDimitry Andric const void* __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__get_deleter(const type_info& __t) const _NOEXCEPT { 2205f757f3fSDimitry Andric return __t == typeid(_Dp) ? std::addressof(__data_.first().second()) : nullptr; 221fe6060f1SDimitry Andric } 222fe6060f1SDimitry Andric 2231ac55f4cSDimitry Andric #endif // _LIBCPP_HAS_NO_RTTI 224fe6060f1SDimitry Andric 225fe6060f1SDimitry Andric template <class _Tp, class _Dp, class _Alloc> 226cb14a3feSDimitry Andric void __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared() _NOEXCEPT { 227fe6060f1SDimitry Andric __data_.first().second()(__data_.first().first()); 228fe6060f1SDimitry Andric __data_.first().second().~_Dp(); 229fe6060f1SDimitry Andric } 230fe6060f1SDimitry Andric 231fe6060f1SDimitry Andric template <class _Tp, class _Dp, class _Alloc> 232cb14a3feSDimitry Andric void __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT { 233fe6060f1SDimitry Andric typedef typename __allocator_traits_rebind<_Alloc, __shared_ptr_pointer>::type _Al; 234fe6060f1SDimitry Andric typedef allocator_traits<_Al> _ATraits; 235fe6060f1SDimitry Andric typedef pointer_traits<typename _ATraits::pointer> _PTraits; 236fe6060f1SDimitry Andric 237fe6060f1SDimitry Andric _Al __a(__data_.second()); 238fe6060f1SDimitry Andric __data_.second().~_Alloc(); 239fe6060f1SDimitry Andric __a.deallocate(_PTraits::pointer_to(*this), 1); 240fe6060f1SDimitry Andric } 241fe6060f1SDimitry Andric 2421ac55f4cSDimitry Andric // This tag is used to instantiate an allocator type. The various shared_ptr control blocks 2431ac55f4cSDimitry Andric // detect that the allocator has been instantiated for this type and perform alternative 2441ac55f4cSDimitry Andric // initialization/destruction based on that. 2451ac55f4cSDimitry Andric struct __for_overwrite_tag {}; 246bdd1243dSDimitry Andric 247fe6060f1SDimitry Andric template <class _Tp, class _Alloc> 248cb14a3feSDimitry Andric struct __shared_ptr_emplace : __shared_weak_count { 249cb14a3feSDimitry Andric template <class... _Args, 250cb14a3feSDimitry Andric class _Allocator = _Alloc, 251cb14a3feSDimitry Andric __enable_if_t<is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0> 252cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&...) : __storage_(std::move(__a)) { 253cb14a3feSDimitry Andric static_assert( 254cb14a3feSDimitry Andric sizeof...(_Args) == 0, "No argument should be provided to the control block when using _for_overwrite"); 2551ac55f4cSDimitry Andric ::new ((void*)__get_elem()) _Tp; 2565f757f3fSDimitry Andric } 2575f757f3fSDimitry Andric 258cb14a3feSDimitry Andric template <class... _Args, 259cb14a3feSDimitry Andric class _Allocator = _Alloc, 260cb14a3feSDimitry Andric __enable_if_t<!is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0> 261cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __shared_ptr_emplace(_Alloc __a, _Args&&... __args) : __storage_(std::move(__a)) { 262*0fca6ea1SDimitry Andric using _TpAlloc = typename __allocator_traits_rebind<_Alloc, __remove_cv_t<_Tp> >::type; 263fe6060f1SDimitry Andric _TpAlloc __tmp(*__get_alloc()); 2645f757f3fSDimitry Andric allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), std::forward<_Args>(__args)...); 265fe6060f1SDimitry Andric } 266fe6060f1SDimitry Andric 267cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Alloc* __get_alloc() _NOEXCEPT { return __storage_.__get_alloc(); } 268fe6060f1SDimitry Andric 269cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Tp* __get_elem() _NOEXCEPT { return __storage_.__get_elem(); } 270fe6060f1SDimitry Andric 271fe6060f1SDimitry Andric private: 272cb14a3feSDimitry Andric template <class _Allocator = _Alloc, 273cb14a3feSDimitry Andric __enable_if_t<is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0> 2745f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __on_zero_shared_impl() _NOEXCEPT { 2751ac55f4cSDimitry Andric __get_elem()->~_Tp(); 2765f757f3fSDimitry Andric } 2775f757f3fSDimitry Andric 278cb14a3feSDimitry Andric template <class _Allocator = _Alloc, 279cb14a3feSDimitry Andric __enable_if_t<!is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0> 2805f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __on_zero_shared_impl() _NOEXCEPT { 281*0fca6ea1SDimitry Andric using _TpAlloc = typename __allocator_traits_rebind<_Allocator, __remove_cv_t<_Tp> >::type; 282fe6060f1SDimitry Andric _TpAlloc __tmp(*__get_alloc()); 283fe6060f1SDimitry Andric allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem()); 2841ac55f4cSDimitry Andric } 2855f757f3fSDimitry Andric 286cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override { __on_zero_shared_impl(); } 287fe6060f1SDimitry Andric 28806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override { 289fe6060f1SDimitry Andric using _ControlBlockAlloc = typename __allocator_traits_rebind<_Alloc, __shared_ptr_emplace>::type; 290fe6060f1SDimitry Andric using _ControlBlockPointer = typename allocator_traits<_ControlBlockAlloc>::pointer; 291fe6060f1SDimitry Andric _ControlBlockAlloc __tmp(*__get_alloc()); 292fe6060f1SDimitry Andric __storage_.~_Storage(); 293cb14a3feSDimitry Andric allocator_traits<_ControlBlockAlloc>::deallocate(__tmp, pointer_traits<_ControlBlockPointer>::pointer_to(*this), 1); 294fe6060f1SDimitry Andric } 295fe6060f1SDimitry Andric 296fe6060f1SDimitry Andric // This class implements the control block for non-array shared pointers created 297fe6060f1SDimitry Andric // through `std::allocate_shared` and `std::make_shared`. 298fe6060f1SDimitry Andric // 299fe6060f1SDimitry Andric // In previous versions of the library, we used a compressed pair to store 300fe6060f1SDimitry Andric // both the _Alloc and the _Tp. This implies using EBO, which is incompatible 301fe6060f1SDimitry Andric // with Allocator construction for _Tp. To allow implementing P0674 in C++20, 302fe6060f1SDimitry Andric // we now use a properly aligned char buffer while making sure that we maintain 303fe6060f1SDimitry Andric // the same layout that we had when we used a compressed pair. 304fe6060f1SDimitry Andric using _CompressedPair = __compressed_pair<_Alloc, _Tp>; 305fe6060f1SDimitry Andric struct _ALIGNAS_TYPE(_CompressedPair) _Storage { 306fe6060f1SDimitry Andric char __blob_[sizeof(_CompressedPair)]; 307fe6060f1SDimitry Andric 308cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit _Storage(_Alloc&& __a) { ::new ((void*)__get_alloc()) _Alloc(std::move(__a)); } 309cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI ~_Storage() { __get_alloc()->~_Alloc(); } 31006c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI _Alloc* __get_alloc() _NOEXCEPT { 311fe6060f1SDimitry Andric _CompressedPair* __as_pair = reinterpret_cast<_CompressedPair*>(__blob_); 312fe6060f1SDimitry Andric typename _CompressedPair::_Base1* __first = _CompressedPair::__get_first_base(__as_pair); 313fe6060f1SDimitry Andric _Alloc* __alloc = reinterpret_cast<_Alloc*>(__first); 314fe6060f1SDimitry Andric return __alloc; 315fe6060f1SDimitry Andric } 31606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _Tp* __get_elem() _NOEXCEPT { 317fe6060f1SDimitry Andric _CompressedPair* __as_pair = reinterpret_cast<_CompressedPair*>(__blob_); 318fe6060f1SDimitry Andric typename _CompressedPair::_Base2* __second = _CompressedPair::__get_second_base(__as_pair); 319fe6060f1SDimitry Andric _Tp* __elem = reinterpret_cast<_Tp*>(__second); 320fe6060f1SDimitry Andric return __elem; 321fe6060f1SDimitry Andric } 322fe6060f1SDimitry Andric }; 323fe6060f1SDimitry Andric 324fe6060f1SDimitry Andric static_assert(_LIBCPP_ALIGNOF(_Storage) == _LIBCPP_ALIGNOF(_CompressedPair), ""); 325fe6060f1SDimitry Andric static_assert(sizeof(_Storage) == sizeof(_CompressedPair), ""); 326fe6060f1SDimitry Andric _Storage __storage_; 327fe6060f1SDimitry Andric }; 328fe6060f1SDimitry Andric 329fe6060f1SDimitry Andric struct __shared_ptr_dummy_rebind_allocator_type; 330fe6060f1SDimitry Andric template <> 331cb14a3feSDimitry Andric class _LIBCPP_TEMPLATE_VIS allocator<__shared_ptr_dummy_rebind_allocator_type> { 332fe6060f1SDimitry Andric public: 333fe6060f1SDimitry Andric template <class _Other> 334cb14a3feSDimitry Andric struct rebind { 335fe6060f1SDimitry Andric typedef allocator<_Other> other; 336fe6060f1SDimitry Andric }; 337fe6060f1SDimitry Andric }; 338fe6060f1SDimitry Andric 339cb14a3feSDimitry Andric template <class _Tp> 340cb14a3feSDimitry Andric class _LIBCPP_TEMPLATE_VIS enable_shared_from_this; 341fe6060f1SDimitry Andric 3421ac55f4cSDimitry Andric // http://eel.is/c++draft/util.sharedptr#util.smartptr.shared.general-6 3431ac55f4cSDimitry Andric // A pointer type Y* is said to be compatible with a pointer type T* 3441ac55f4cSDimitry Andric // when either Y* is convertible to T* or Y is U[N] and T is cv U[]. 3451ac55f4cSDimitry Andric #if _LIBCPP_STD_VER >= 17 3461ac55f4cSDimitry Andric template <class _Yp, class _Tp> 3471ac55f4cSDimitry Andric struct __bounded_convertible_to_unbounded : false_type {}; 3481ac55f4cSDimitry Andric 3491ac55f4cSDimitry Andric template <class _Up, std::size_t _Np, class _Tp> 350cb14a3feSDimitry Andric struct __bounded_convertible_to_unbounded<_Up[_Np], _Tp> : is_same<__remove_cv_t<_Tp>, _Up[]> {}; 3511ac55f4cSDimitry Andric 3521ac55f4cSDimitry Andric template <class _Yp, class _Tp> 353cb14a3feSDimitry Andric struct __compatible_with : _Or< is_convertible<_Yp*, _Tp*>, __bounded_convertible_to_unbounded<_Yp, _Tp> > {}; 354fe6060f1SDimitry Andric #else 3551ac55f4cSDimitry Andric template <class _Yp, class _Tp> 356cb14a3feSDimitry Andric struct __compatible_with : is_convertible<_Yp*, _Tp*> {}; 3571ac55f4cSDimitry Andric #endif // _LIBCPP_STD_VER >= 17 3581ac55f4cSDimitry Andric 3591ac55f4cSDimitry Andric // Constructors that take raw pointers have a different set of "compatible" constraints 3601ac55f4cSDimitry Andric // http://eel.is/c++draft/util.sharedptr#util.smartptr.shared.const-9.1 3611ac55f4cSDimitry Andric // - If T is an array type, then either T is U[N] and Y(*)[N] is convertible to T*, 3621ac55f4cSDimitry Andric // or T is U[] and Y(*)[] is convertible to T*. 3631ac55f4cSDimitry Andric // - If T is not an array type, then Y* is convertible to T*. 3641ac55f4cSDimitry Andric #if _LIBCPP_STD_VER >= 17 3651ac55f4cSDimitry Andric template <class _Yp, class _Tp, class = void> 366cb14a3feSDimitry Andric struct __raw_pointer_compatible_with : _And< _Not<is_array<_Tp>>, is_convertible<_Yp*, _Tp*> > {}; 3671ac55f4cSDimitry Andric 3681ac55f4cSDimitry Andric template <class _Yp, class _Up, std::size_t _Np> 369cb14a3feSDimitry Andric struct __raw_pointer_compatible_with<_Yp, _Up[_Np], __enable_if_t< is_convertible<_Yp (*)[_Np], _Up (*)[_Np]>::value> > 3701ac55f4cSDimitry Andric : true_type {}; 3711ac55f4cSDimitry Andric 3721ac55f4cSDimitry Andric template <class _Yp, class _Up> 373cb14a3feSDimitry Andric struct __raw_pointer_compatible_with<_Yp, _Up[], __enable_if_t< is_convertible<_Yp (*)[], _Up (*)[]>::value> > 3741ac55f4cSDimitry Andric : true_type {}; 3751ac55f4cSDimitry Andric 3761ac55f4cSDimitry Andric #else 3771ac55f4cSDimitry Andric template <class _Yp, class _Tp> 378cb14a3feSDimitry Andric struct __raw_pointer_compatible_with : is_convertible<_Yp*, _Tp*> {}; 3791ac55f4cSDimitry Andric #endif // _LIBCPP_STD_VER >= 17 3801ac55f4cSDimitry Andric 381fe6060f1SDimitry Andric template <class _Ptr, class = void> 382fe6060f1SDimitry Andric struct __is_deletable : false_type {}; 383fe6060f1SDimitry Andric template <class _Ptr> 384bdd1243dSDimitry Andric struct __is_deletable<_Ptr, decltype(delete std::declval<_Ptr>())> : true_type {}; 385fe6060f1SDimitry Andric 386fe6060f1SDimitry Andric template <class _Ptr, class = void> 387fe6060f1SDimitry Andric struct __is_array_deletable : false_type {}; 388fe6060f1SDimitry Andric template <class _Ptr> 389bdd1243dSDimitry Andric struct __is_array_deletable<_Ptr, decltype(delete[] std::declval<_Ptr>())> : true_type {}; 390fe6060f1SDimitry Andric 391cb14a3feSDimitry Andric template <class _Dp, class _Pt, class = decltype(std::declval<_Dp>()(std::declval<_Pt>()))> 39206c3fb27SDimitry Andric true_type __well_formed_deleter_test(int); 393fe6060f1SDimitry Andric 394fe6060f1SDimitry Andric template <class, class> 39506c3fb27SDimitry Andric false_type __well_formed_deleter_test(...); 396fe6060f1SDimitry Andric 397fe6060f1SDimitry Andric template <class _Dp, class _Pt> 398bdd1243dSDimitry Andric struct __well_formed_deleter : decltype(std::__well_formed_deleter_test<_Dp, _Pt>(0)) {}; 399fe6060f1SDimitry Andric 4001ac55f4cSDimitry Andric template <class _Dp, class _Yp, class _Tp> 401cb14a3feSDimitry Andric struct __shared_ptr_deleter_ctor_reqs { 402cb14a3feSDimitry Andric static const bool value = __raw_pointer_compatible_with<_Yp, _Tp>::value && is_move_constructible<_Dp>::value && 4031ac55f4cSDimitry Andric __well_formed_deleter<_Dp, _Yp*>::value; 404fe6060f1SDimitry Andric }; 405fe6060f1SDimitry Andric 406*0fca6ea1SDimitry Andric template <class _Dp> 407*0fca6ea1SDimitry Andric using __shared_ptr_nullptr_deleter_ctor_reqs = _And<is_move_constructible<_Dp>, __well_formed_deleter<_Dp, nullptr_t> >; 408*0fca6ea1SDimitry Andric 409fe6060f1SDimitry Andric #if defined(_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI) 41006c3fb27SDimitry Andric # define _LIBCPP_SHARED_PTR_TRIVIAL_ABI __attribute__((__trivial_abi__)) 411fe6060f1SDimitry Andric #else 412fe6060f1SDimitry Andric # define _LIBCPP_SHARED_PTR_TRIVIAL_ABI 413fe6060f1SDimitry Andric #endif 414fe6060f1SDimitry Andric 415fe6060f1SDimitry Andric template <class _Tp> 416cb14a3feSDimitry Andric class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr { 417*0fca6ea1SDimitry Andric struct __nullptr_sfinae_tag {}; 418*0fca6ea1SDimitry Andric 419fe6060f1SDimitry Andric public: 42006c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17 421fe6060f1SDimitry Andric typedef weak_ptr<_Tp> weak_type; 422fe6060f1SDimitry Andric typedef remove_extent_t<_Tp> element_type; 423fe6060f1SDimitry Andric #else 424fe6060f1SDimitry Andric typedef _Tp element_type; 425fe6060f1SDimitry Andric #endif 426fe6060f1SDimitry Andric 427*0fca6ea1SDimitry Andric // A shared_ptr contains only two raw pointers which point to the heap and move constructing already doesn't require 428*0fca6ea1SDimitry Andric // any bookkeeping, so it's always trivially relocatable. 429*0fca6ea1SDimitry Andric using __trivially_relocatable = shared_ptr; 430*0fca6ea1SDimitry Andric 431fe6060f1SDimitry Andric private: 432fe6060f1SDimitry Andric element_type* __ptr_; 433fe6060f1SDimitry Andric __shared_weak_count* __cntrl_; 434fe6060f1SDimitry Andric 435fe6060f1SDimitry Andric public: 436cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR shared_ptr() _NOEXCEPT : __ptr_(nullptr), __cntrl_(nullptr) {} 437fe6060f1SDimitry Andric 438cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT : __ptr_(nullptr), __cntrl_(nullptr) {} 439349cc55cSDimitry Andric 440cb14a3feSDimitry Andric template <class _Yp, 441*0fca6ea1SDimitry Andric __enable_if_t< _And< __raw_pointer_compatible_with<_Yp, _Tp> 442fe6060f1SDimitry Andric // In C++03 we get errors when trying to do SFINAE with the 443fe6060f1SDimitry Andric // delete operator, so we always pretend that it's deletable. 444fe6060f1SDimitry Andric // The same happens on GCC. 445fe6060f1SDimitry Andric #if !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_COMPILER_GCC) 446cb14a3feSDimitry Andric , 447cb14a3feSDimitry Andric _If<is_array<_Tp>::value, __is_array_deletable<_Yp*>, __is_deletable<_Yp*> > 448fe6060f1SDimitry Andric #endif 449*0fca6ea1SDimitry Andric >::value, 450*0fca6ea1SDimitry Andric int> = 0> 45106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit shared_ptr(_Yp* __p) : __ptr_(__p) { 452fe6060f1SDimitry Andric unique_ptr<_Yp> __hold(__p); 453fe6060f1SDimitry Andric typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; 454fe6060f1SDimitry Andric typedef __shared_ptr_pointer<_Yp*, __shared_ptr_default_delete<_Tp, _Yp>, _AllocT> _CntrlBlk; 455fe6060f1SDimitry Andric __cntrl_ = new _CntrlBlk(__p, __shared_ptr_default_delete<_Tp, _Yp>(), _AllocT()); 456fe6060f1SDimitry Andric __hold.release(); 457fe6060f1SDimitry Andric __enable_weak_this(__p, __p); 458fe6060f1SDimitry Andric } 459fe6060f1SDimitry Andric 460*0fca6ea1SDimitry Andric template <class _Yp, class _Dp, __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value, int> = 0> 461cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr(_Yp* __p, _Dp __d) : __ptr_(__p) { 46206c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 463cb14a3feSDimitry Andric try { 46406c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 465fe6060f1SDimitry Andric typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; 466fe6060f1SDimitry Andric typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT> _CntrlBlk; 467fe6060f1SDimitry Andric #ifndef _LIBCPP_CXX03_LANG 4685f757f3fSDimitry Andric __cntrl_ = new _CntrlBlk(__p, std::move(__d), _AllocT()); 469fe6060f1SDimitry Andric #else 470fe6060f1SDimitry Andric __cntrl_ = new _CntrlBlk(__p, __d, _AllocT()); 471fe6060f1SDimitry Andric #endif // not _LIBCPP_CXX03_LANG 472fe6060f1SDimitry Andric __enable_weak_this(__p, __p); 47306c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 474cb14a3feSDimitry Andric } catch (...) { 475fe6060f1SDimitry Andric __d(__p); 476fe6060f1SDimitry Andric throw; 477fe6060f1SDimitry Andric } 47806c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 479fe6060f1SDimitry Andric } 480fe6060f1SDimitry Andric 481cb14a3feSDimitry Andric template <class _Yp, 482cb14a3feSDimitry Andric class _Dp, 483cb14a3feSDimitry Andric class _Alloc, 484*0fca6ea1SDimitry Andric __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value, int> = 0> 485cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr(_Yp* __p, _Dp __d, _Alloc __a) : __ptr_(__p) { 48606c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 487cb14a3feSDimitry Andric try { 48806c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 489fe6060f1SDimitry Andric typedef __shared_ptr_pointer<_Yp*, _Dp, _Alloc> _CntrlBlk; 490fe6060f1SDimitry Andric typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2; 491fe6060f1SDimitry Andric typedef __allocator_destructor<_A2> _D2; 492fe6060f1SDimitry Andric _A2 __a2(__a); 493fe6060f1SDimitry Andric unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1)); 4945f757f3fSDimitry Andric ::new ((void*)std::addressof(*__hold2.get())) 495fe6060f1SDimitry Andric #ifndef _LIBCPP_CXX03_LANG 4965f757f3fSDimitry Andric _CntrlBlk(__p, std::move(__d), __a); 497fe6060f1SDimitry Andric #else 498fe6060f1SDimitry Andric _CntrlBlk(__p, __d, __a); 499fe6060f1SDimitry Andric #endif // not _LIBCPP_CXX03_LANG 5005f757f3fSDimitry Andric __cntrl_ = std::addressof(*__hold2.release()); 501fe6060f1SDimitry Andric __enable_weak_this(__p, __p); 50206c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 503cb14a3feSDimitry Andric } catch (...) { 504fe6060f1SDimitry Andric __d(__p); 505fe6060f1SDimitry Andric throw; 506fe6060f1SDimitry Andric } 50706c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 508fe6060f1SDimitry Andric } 509fe6060f1SDimitry Andric 510349cc55cSDimitry Andric template <class _Dp> 511*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr( 512*0fca6ea1SDimitry Andric nullptr_t __p, 513*0fca6ea1SDimitry Andric _Dp __d, 514*0fca6ea1SDimitry Andric __enable_if_t<__shared_ptr_nullptr_deleter_ctor_reqs<_Dp>::value, __nullptr_sfinae_tag> = __nullptr_sfinae_tag()) 515*0fca6ea1SDimitry Andric : __ptr_(nullptr) { 51606c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 517cb14a3feSDimitry Andric try { 51806c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 519349cc55cSDimitry Andric typedef typename __shared_ptr_default_allocator<_Tp>::type _AllocT; 520349cc55cSDimitry Andric typedef __shared_ptr_pointer<nullptr_t, _Dp, _AllocT> _CntrlBlk; 521349cc55cSDimitry Andric #ifndef _LIBCPP_CXX03_LANG 5225f757f3fSDimitry Andric __cntrl_ = new _CntrlBlk(__p, std::move(__d), _AllocT()); 523349cc55cSDimitry Andric #else 524349cc55cSDimitry Andric __cntrl_ = new _CntrlBlk(__p, __d, _AllocT()); 525349cc55cSDimitry Andric #endif // not _LIBCPP_CXX03_LANG 52606c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 527cb14a3feSDimitry Andric } catch (...) { 528349cc55cSDimitry Andric __d(__p); 529349cc55cSDimitry Andric throw; 530349cc55cSDimitry Andric } 53106c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 532349cc55cSDimitry Andric } 533349cc55cSDimitry Andric 534fe6060f1SDimitry Andric template <class _Dp, class _Alloc> 535*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr( 536*0fca6ea1SDimitry Andric nullptr_t __p, 537*0fca6ea1SDimitry Andric _Dp __d, 538*0fca6ea1SDimitry Andric _Alloc __a, 539*0fca6ea1SDimitry Andric __enable_if_t<__shared_ptr_nullptr_deleter_ctor_reqs<_Dp>::value, __nullptr_sfinae_tag> = __nullptr_sfinae_tag()) 540*0fca6ea1SDimitry Andric : __ptr_(nullptr) { 54106c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 542cb14a3feSDimitry Andric try { 54306c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 544fe6060f1SDimitry Andric typedef __shared_ptr_pointer<nullptr_t, _Dp, _Alloc> _CntrlBlk; 545fe6060f1SDimitry Andric typedef typename __allocator_traits_rebind<_Alloc, _CntrlBlk>::type _A2; 546fe6060f1SDimitry Andric typedef __allocator_destructor<_A2> _D2; 547fe6060f1SDimitry Andric _A2 __a2(__a); 548fe6060f1SDimitry Andric unique_ptr<_CntrlBlk, _D2> __hold2(__a2.allocate(1), _D2(__a2, 1)); 5495f757f3fSDimitry Andric ::new ((void*)std::addressof(*__hold2.get())) 550fe6060f1SDimitry Andric #ifndef _LIBCPP_CXX03_LANG 5515f757f3fSDimitry Andric _CntrlBlk(__p, std::move(__d), __a); 552fe6060f1SDimitry Andric #else 553fe6060f1SDimitry Andric _CntrlBlk(__p, __d, __a); 554fe6060f1SDimitry Andric #endif // not _LIBCPP_CXX03_LANG 5555f757f3fSDimitry Andric __cntrl_ = std::addressof(*__hold2.release()); 55606c3fb27SDimitry Andric #ifndef _LIBCPP_HAS_NO_EXCEPTIONS 557cb14a3feSDimitry Andric } catch (...) { 558fe6060f1SDimitry Andric __d(__p); 559fe6060f1SDimitry Andric throw; 560fe6060f1SDimitry Andric } 56106c3fb27SDimitry Andric #endif // _LIBCPP_HAS_NO_EXCEPTIONS 562fe6060f1SDimitry Andric } 563fe6060f1SDimitry Andric 564fe6060f1SDimitry Andric template <class _Yp> 565cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) _NOEXCEPT 566fe6060f1SDimitry Andric : __ptr_(__p), 567cb14a3feSDimitry Andric __cntrl_(__r.__cntrl_) { 568fe6060f1SDimitry Andric if (__cntrl_) 569fe6060f1SDimitry Andric __cntrl_->__add_shared(); 570fe6060f1SDimitry Andric } 571fe6060f1SDimitry Andric 57206c3fb27SDimitry Andric // LWG-2996 57306c3fb27SDimitry Andric // We don't backport because it is an evolutionary change. 57406c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 57506c3fb27SDimitry Andric template <class _Yp> 57606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr(shared_ptr<_Yp>&& __r, element_type* __p) noexcept 577cb14a3feSDimitry Andric : __ptr_(__p), __cntrl_(__r.__cntrl_) { 57806c3fb27SDimitry Andric __r.__ptr_ = nullptr; 57906c3fb27SDimitry Andric __r.__cntrl_ = nullptr; 58006c3fb27SDimitry Andric } 58106c3fb27SDimitry Andric #endif 58206c3fb27SDimitry Andric 583cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr(const shared_ptr& __r) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_) { 584fe6060f1SDimitry Andric if (__cntrl_) 585fe6060f1SDimitry Andric __cntrl_->__add_shared(); 586fe6060f1SDimitry Andric } 587fe6060f1SDimitry Andric 588*0fca6ea1SDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> = 0> 589cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr(const shared_ptr<_Yp>& __r) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_) { 590fe6060f1SDimitry Andric if (__cntrl_) 591fe6060f1SDimitry Andric __cntrl_->__add_shared(); 592fe6060f1SDimitry Andric } 593fe6060f1SDimitry Andric 594cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr(shared_ptr&& __r) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_) { 595fe6060f1SDimitry Andric __r.__ptr_ = nullptr; 596fe6060f1SDimitry Andric __r.__cntrl_ = nullptr; 597fe6060f1SDimitry Andric } 598fe6060f1SDimitry Andric 599*0fca6ea1SDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> = 0> 600cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr(shared_ptr<_Yp>&& __r) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_) { 601fe6060f1SDimitry Andric __r.__ptr_ = nullptr; 602fe6060f1SDimitry Andric __r.__cntrl_ = nullptr; 603fe6060f1SDimitry Andric } 604fe6060f1SDimitry Andric 605*0fca6ea1SDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> = 0> 606cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit shared_ptr(const weak_ptr<_Yp>& __r) 607cb14a3feSDimitry Andric : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_ ? __r.__cntrl_->lock() : __r.__cntrl_) { 608349cc55cSDimitry Andric if (__cntrl_ == nullptr) 609349cc55cSDimitry Andric __throw_bad_weak_ptr(); 610349cc55cSDimitry Andric } 611349cc55cSDimitry Andric 612fe6060f1SDimitry Andric #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) 613*0fca6ea1SDimitry Andric template <class _Yp, __enable_if_t<is_convertible<_Yp*, element_type*>::value, int> = 0> 614cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr(auto_ptr<_Yp>&& __r) : __ptr_(__r.get()) { 615*0fca6ea1SDimitry Andric typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, allocator<__remove_cv_t<_Yp> > > _CntrlBlk; 616*0fca6ea1SDimitry Andric __cntrl_ = new _CntrlBlk(__r.get(), default_delete<_Yp>(), allocator<__remove_cv_t<_Yp> >()); 617fe6060f1SDimitry Andric __enable_weak_this(__r.get(), __r.get()); 618fe6060f1SDimitry Andric __r.release(); 619fe6060f1SDimitry Andric } 620fe6060f1SDimitry Andric #endif 621fe6060f1SDimitry Andric 622cb14a3feSDimitry Andric template <class _Yp, 623cb14a3feSDimitry Andric class _Dp, 624*0fca6ea1SDimitry Andric __enable_if_t<!is_lvalue_reference<_Dp>::value && __compatible_with<_Yp, _Tp>::value && 625*0fca6ea1SDimitry Andric is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, 626*0fca6ea1SDimitry Andric int> = 0> 627cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr(unique_ptr<_Yp, _Dp>&& __r) : __ptr_(__r.get()) { 62806c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 14 629fe6060f1SDimitry Andric if (__ptr_ == nullptr) 630fe6060f1SDimitry Andric __cntrl_ = nullptr; 631fe6060f1SDimitry Andric else 632fe6060f1SDimitry Andric #endif 633fe6060f1SDimitry Andric { 634fe6060f1SDimitry Andric typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; 635fe6060f1SDimitry Andric typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer, _Dp, _AllocT> _CntrlBlk; 63681ad6265SDimitry Andric __cntrl_ = new _CntrlBlk(__r.get(), std::move(__r.get_deleter()), _AllocT()); 637fe6060f1SDimitry Andric __enable_weak_this(__r.get(), __r.get()); 638fe6060f1SDimitry Andric } 639fe6060f1SDimitry Andric __r.release(); 640fe6060f1SDimitry Andric } 641fe6060f1SDimitry Andric 642cb14a3feSDimitry Andric template <class _Yp, 643cb14a3feSDimitry Andric class _Dp, 644cb14a3feSDimitry Andric class = void, 645*0fca6ea1SDimitry Andric __enable_if_t<is_lvalue_reference<_Dp>::value && __compatible_with<_Yp, _Tp>::value && 646*0fca6ea1SDimitry Andric is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value, 647*0fca6ea1SDimitry Andric int> = 0> 648cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr(unique_ptr<_Yp, _Dp>&& __r) : __ptr_(__r.get()) { 64906c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 14 650fe6060f1SDimitry Andric if (__ptr_ == nullptr) 651fe6060f1SDimitry Andric __cntrl_ = nullptr; 652fe6060f1SDimitry Andric else 653fe6060f1SDimitry Andric #endif 654fe6060f1SDimitry Andric { 655fe6060f1SDimitry Andric typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT; 656fe6060f1SDimitry Andric typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer, 657bdd1243dSDimitry Andric reference_wrapper<__libcpp_remove_reference_t<_Dp> >, 658cb14a3feSDimitry Andric _AllocT> 659cb14a3feSDimitry Andric _CntrlBlk; 6605f757f3fSDimitry Andric __cntrl_ = new _CntrlBlk(__r.get(), std::ref(__r.get_deleter()), _AllocT()); 661fe6060f1SDimitry Andric __enable_weak_this(__r.get(), __r.get()); 662fe6060f1SDimitry Andric } 663fe6060f1SDimitry Andric __r.release(); 664fe6060f1SDimitry Andric } 665fe6060f1SDimitry Andric 666cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI ~shared_ptr() { 667fe6060f1SDimitry Andric if (__cntrl_) 668fe6060f1SDimitry Andric __cntrl_->__release_shared(); 669fe6060f1SDimitry Andric } 670fe6060f1SDimitry Andric 671cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp>& operator=(const shared_ptr& __r) _NOEXCEPT { 672fe6060f1SDimitry Andric shared_ptr(__r).swap(*this); 673fe6060f1SDimitry Andric return *this; 674fe6060f1SDimitry Andric } 675fe6060f1SDimitry Andric 676*0fca6ea1SDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> = 0> 677cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp>& operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT { 678fe6060f1SDimitry Andric shared_ptr(__r).swap(*this); 679fe6060f1SDimitry Andric return *this; 680fe6060f1SDimitry Andric } 681fe6060f1SDimitry Andric 682cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp>& operator=(shared_ptr&& __r) _NOEXCEPT { 6835f757f3fSDimitry Andric shared_ptr(std::move(__r)).swap(*this); 684fe6060f1SDimitry Andric return *this; 685fe6060f1SDimitry Andric } 686fe6060f1SDimitry Andric 687*0fca6ea1SDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> = 0> 688cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp>& operator=(shared_ptr<_Yp>&& __r) { 6895f757f3fSDimitry Andric shared_ptr(std::move(__r)).swap(*this); 690fe6060f1SDimitry Andric return *this; 691fe6060f1SDimitry Andric } 692fe6060f1SDimitry Andric 693fe6060f1SDimitry Andric #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) 694cb14a3feSDimitry Andric template <class _Yp, 695*0fca6ea1SDimitry Andric __enable_if_t<!is_array<_Yp>::value && is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value, 696*0fca6ea1SDimitry Andric int> = 0> 697cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp>& operator=(auto_ptr<_Yp>&& __r) { 6985f757f3fSDimitry Andric shared_ptr(std::move(__r)).swap(*this); 699fe6060f1SDimitry Andric return *this; 700fe6060f1SDimitry Andric } 701fe6060f1SDimitry Andric #endif 702fe6060f1SDimitry Andric 703*0fca6ea1SDimitry Andric template <class _Yp, 704cb14a3feSDimitry Andric class _Dp, 705*0fca6ea1SDimitry Andric __enable_if_t<_And< __compatible_with<_Yp, _Tp>, 706*0fca6ea1SDimitry Andric is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*> >::value, 707*0fca6ea1SDimitry Andric int> = 0> 708cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp>& operator=(unique_ptr<_Yp, _Dp>&& __r) { 7095f757f3fSDimitry Andric shared_ptr(std::move(__r)).swap(*this); 710fe6060f1SDimitry Andric return *this; 711fe6060f1SDimitry Andric } 712fe6060f1SDimitry Andric 713cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void swap(shared_ptr& __r) _NOEXCEPT { 7145f757f3fSDimitry Andric std::swap(__ptr_, __r.__ptr_); 7155f757f3fSDimitry Andric std::swap(__cntrl_, __r.__cntrl_); 716fe6060f1SDimitry Andric } 717fe6060f1SDimitry Andric 718cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void reset() _NOEXCEPT { shared_ptr().swap(*this); } 719fe6060f1SDimitry Andric 720*0fca6ea1SDimitry Andric template <class _Yp, __enable_if_t<__raw_pointer_compatible_with<_Yp, _Tp>::value, int> = 0> 721cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p) { 722fe6060f1SDimitry Andric shared_ptr(__p).swap(*this); 723fe6060f1SDimitry Andric } 724fe6060f1SDimitry Andric 725*0fca6ea1SDimitry Andric template <class _Yp, class _Dp, __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value, int> = 0> 726cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p, _Dp __d) { 727fe6060f1SDimitry Andric shared_ptr(__p, __d).swap(*this); 728fe6060f1SDimitry Andric } 729fe6060f1SDimitry Andric 730cb14a3feSDimitry Andric template <class _Yp, 731cb14a3feSDimitry Andric class _Dp, 732cb14a3feSDimitry Andric class _Alloc, 733*0fca6ea1SDimitry Andric __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value, int> = 0> 734cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void reset(_Yp* __p, _Dp __d, _Alloc __a) { 735fe6060f1SDimitry Andric shared_ptr(__p, __d, __a).swap(*this); 736fe6060f1SDimitry Andric } 737fe6060f1SDimitry Andric 738cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI element_type* get() const _NOEXCEPT { return __ptr_; } 739cb14a3feSDimitry Andric 740cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __add_lvalue_reference_t<element_type> operator*() const _NOEXCEPT { return *__ptr_; } 741cb14a3feSDimitry Andric 742cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI element_type* operator->() const _NOEXCEPT { 743cb14a3feSDimitry Andric static_assert(!is_array<_Tp>::value, "std::shared_ptr<T>::operator-> is only valid when T is not an array type."); 744349cc55cSDimitry Andric return __ptr_; 745349cc55cSDimitry Andric } 746349cc55cSDimitry Andric 747cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI long use_count() const _NOEXCEPT { return __cntrl_ ? __cntrl_->use_count() : 0; } 748349cc55cSDimitry Andric 749647cbc5dSDimitry Andric #if _LIBCPP_STD_VER < 20 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_SHARED_PTR_UNIQUE) 750647cbc5dSDimitry Andric _LIBCPP_DEPRECATED_IN_CXX17 _LIBCPP_HIDE_FROM_ABI bool unique() const _NOEXCEPT { return use_count() == 1; } 751647cbc5dSDimitry Andric #endif 752349cc55cSDimitry Andric 753cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return get() != nullptr; } 754349cc55cSDimitry Andric 755349cc55cSDimitry Andric template <class _Up> 756cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool owner_before(shared_ptr<_Up> const& __p) const _NOEXCEPT { 757349cc55cSDimitry Andric return __cntrl_ < __p.__cntrl_; 758349cc55cSDimitry Andric } 759349cc55cSDimitry Andric 760349cc55cSDimitry Andric template <class _Up> 761cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool owner_before(weak_ptr<_Up> const& __p) const _NOEXCEPT { 762349cc55cSDimitry Andric return __cntrl_ < __p.__cntrl_; 763349cc55cSDimitry Andric } 764349cc55cSDimitry Andric 765cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool __owner_equivalent(const shared_ptr& __p) const { return __cntrl_ == __p.__cntrl_; } 766349cc55cSDimitry Andric 76706c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17 768cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __add_lvalue_reference_t<element_type> operator[](ptrdiff_t __i) const { 769cb14a3feSDimitry Andric static_assert(is_array<_Tp>::value, "std::shared_ptr<T>::operator[] is only valid when T is an array type."); 770349cc55cSDimitry Andric return __ptr_[__i]; 771349cc55cSDimitry Andric } 772349cc55cSDimitry Andric #endif 773349cc55cSDimitry Andric 7741ac55f4cSDimitry Andric #ifndef _LIBCPP_HAS_NO_RTTI 775349cc55cSDimitry Andric template <class _Dp> 776cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _Dp* __get_deleter() const _NOEXCEPT { 777cb14a3feSDimitry Andric return static_cast<_Dp*>(__cntrl_ ? const_cast<void*>(__cntrl_->__get_deleter(typeid(_Dp))) : nullptr); 778349cc55cSDimitry Andric } 7791ac55f4cSDimitry Andric #endif // _LIBCPP_HAS_NO_RTTI 780349cc55cSDimitry Andric 781349cc55cSDimitry Andric template <class _Yp, class _CntrlBlk> 782cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI static shared_ptr<_Tp> __create_with_control_block(_Yp* __p, _CntrlBlk* __cntrl) _NOEXCEPT { 783349cc55cSDimitry Andric shared_ptr<_Tp> __r; 784349cc55cSDimitry Andric __r.__ptr_ = __p; 785349cc55cSDimitry Andric __r.__cntrl_ = __cntrl; 786349cc55cSDimitry Andric __r.__enable_weak_this(__r.__ptr_, __r.__ptr_); 787349cc55cSDimitry Andric return __r; 788349cc55cSDimitry Andric } 789349cc55cSDimitry Andric 790349cc55cSDimitry Andric private: 791349cc55cSDimitry Andric template <class _Yp, bool = is_function<_Yp>::value> 792cb14a3feSDimitry Andric struct __shared_ptr_default_allocator { 793*0fca6ea1SDimitry Andric typedef allocator<__remove_cv_t<_Yp> > type; 794349cc55cSDimitry Andric }; 795349cc55cSDimitry Andric 796349cc55cSDimitry Andric template <class _Yp> 797cb14a3feSDimitry Andric struct __shared_ptr_default_allocator<_Yp, true> { 798349cc55cSDimitry Andric typedef allocator<__shared_ptr_dummy_rebind_allocator_type> type; 799349cc55cSDimitry Andric }; 800349cc55cSDimitry Andric 801cb14a3feSDimitry Andric template <class _Yp, 802cb14a3feSDimitry Andric class _OrigPtr, 803*0fca6ea1SDimitry Andric __enable_if_t<is_convertible<_OrigPtr*, const enable_shared_from_this<_Yp>*>::value, int> = 0> 804cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __enable_weak_this(const enable_shared_from_this<_Yp>* __e, _OrigPtr* __ptr) _NOEXCEPT { 805bdd1243dSDimitry Andric typedef __remove_cv_t<_Yp> _RawYp; 806cb14a3feSDimitry Andric if (__e && __e->__weak_this_.expired()) { 807cb14a3feSDimitry Andric __e->__weak_this_ = shared_ptr<_RawYp>(*this, const_cast<_RawYp*>(static_cast<const _Yp*>(__ptr))); 808349cc55cSDimitry Andric } 809349cc55cSDimitry Andric } 810349cc55cSDimitry Andric 811349cc55cSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __enable_weak_this(...) _NOEXCEPT {} 812349cc55cSDimitry Andric 813349cc55cSDimitry Andric template <class, class _Yp> 814cb14a3feSDimitry Andric struct __shared_ptr_default_delete : default_delete<_Yp> {}; 815349cc55cSDimitry Andric 816349cc55cSDimitry Andric template <class _Yp, class _Un, size_t _Sz> 817cb14a3feSDimitry Andric struct __shared_ptr_default_delete<_Yp[_Sz], _Un> : default_delete<_Yp[]> {}; 818349cc55cSDimitry Andric 819349cc55cSDimitry Andric template <class _Yp, class _Un> 820cb14a3feSDimitry Andric struct __shared_ptr_default_delete<_Yp[], _Un> : default_delete<_Yp[]> {}; 821349cc55cSDimitry Andric 822cb14a3feSDimitry Andric template <class _Up> 823cb14a3feSDimitry Andric friend class _LIBCPP_TEMPLATE_VIS shared_ptr; 824cb14a3feSDimitry Andric template <class _Up> 825cb14a3feSDimitry Andric friend class _LIBCPP_TEMPLATE_VIS weak_ptr; 826349cc55cSDimitry Andric }; 827349cc55cSDimitry Andric 82806c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17 829349cc55cSDimitry Andric template <class _Tp> 830349cc55cSDimitry Andric shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>; 831349cc55cSDimitry Andric template <class _Tp, class _Dp> 832349cc55cSDimitry Andric shared_ptr(unique_ptr<_Tp, _Dp>) -> shared_ptr<_Tp>; 833349cc55cSDimitry Andric #endif 834349cc55cSDimitry Andric 835fe6060f1SDimitry Andric // 836fe6060f1SDimitry Andric // std::allocate_shared and std::make_shared 837fe6060f1SDimitry Andric // 838*0fca6ea1SDimitry Andric template <class _Tp, class _Alloc, class... _Args, __enable_if_t<!is_array<_Tp>::value, int> = 0> 839cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a, _Args&&... __args) { 840fe6060f1SDimitry Andric using _ControlBlock = __shared_ptr_emplace<_Tp, _Alloc>; 841fe6060f1SDimitry Andric using _ControlBlockAllocator = typename __allocator_traits_rebind<_Alloc, _ControlBlock>::type; 842fe6060f1SDimitry Andric __allocation_guard<_ControlBlockAllocator> __guard(__a, 1); 8435f757f3fSDimitry Andric ::new ((void*)std::addressof(*__guard.__get())) _ControlBlock(__a, std::forward<_Args>(__args)...); 844fe6060f1SDimitry Andric auto __control_block = __guard.__release_ptr(); 845cb14a3feSDimitry Andric return shared_ptr<_Tp>::__create_with_control_block( 846cb14a3feSDimitry Andric (*__control_block).__get_elem(), std::addressof(*__control_block)); 847fe6060f1SDimitry Andric } 848fe6060f1SDimitry Andric 849*0fca6ea1SDimitry Andric template <class _Tp, class... _Args, __enable_if_t<!is_array<_Tp>::value, int> = 0> 850cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(_Args&&... __args) { 851*0fca6ea1SDimitry Andric return std::allocate_shared<_Tp>(allocator<__remove_cv_t<_Tp> >(), std::forward<_Args>(__args)...); 852fe6060f1SDimitry Andric } 853fe6060f1SDimitry Andric 854bdd1243dSDimitry Andric #if _LIBCPP_STD_VER >= 20 855bdd1243dSDimitry Andric 856bdd1243dSDimitry Andric template <class _Tp, class _Alloc, __enable_if_t<!is_array<_Tp>::value, int> = 0> 857cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a) { 8581ac55f4cSDimitry Andric using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>; 8591ac55f4cSDimitry Andric _ForOverwriteAllocator __alloc(__a); 8601ac55f4cSDimitry Andric return std::allocate_shared<_Tp>(__alloc); 861bdd1243dSDimitry Andric } 862bdd1243dSDimitry Andric 863bdd1243dSDimitry Andric template <class _Tp, __enable_if_t<!is_array<_Tp>::value, int> = 0> 864cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite() { 865*0fca6ea1SDimitry Andric return std::allocate_shared_for_overwrite<_Tp>(allocator<__remove_cv_t<_Tp>>()); 866bdd1243dSDimitry Andric } 867bdd1243dSDimitry Andric 868bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER >= 20 869bdd1243dSDimitry Andric 87006c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17 87181ad6265SDimitry Andric 87281ad6265SDimitry Andric template <size_t _Alignment> 87381ad6265SDimitry Andric struct __sp_aligned_storage { 87481ad6265SDimitry Andric alignas(_Alignment) char __storage[_Alignment]; 87581ad6265SDimitry Andric }; 87681ad6265SDimitry Andric 87781ad6265SDimitry Andric template <class _Tp, class _Alloc> 87881ad6265SDimitry Andric struct __unbounded_array_control_block; 87981ad6265SDimitry Andric 88081ad6265SDimitry Andric template <class _Tp, class _Alloc> 881cb14a3feSDimitry Andric struct __unbounded_array_control_block<_Tp[], _Alloc> : __shared_weak_count { 882cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp* __get_data() noexcept { return __data_; } 88381ad6265SDimitry Andric 884cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __unbounded_array_control_block( 885cb14a3feSDimitry Andric _Alloc const& __alloc, size_t __count, _Tp const& __arg) 886cb14a3feSDimitry Andric : __alloc_(__alloc), __count_(__count) { 8871ac55f4cSDimitry Andric std::__uninitialized_allocator_fill_n_multidimensional(__alloc_, std::begin(__data_), __count_, __arg); 88881ad6265SDimitry Andric } 88981ad6265SDimitry Andric 890cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __unbounded_array_control_block(_Alloc const& __alloc, size_t __count) 891cb14a3feSDimitry Andric : __alloc_(__alloc), __count_(__count) { 892bdd1243dSDimitry Andric # if _LIBCPP_STD_VER >= 20 8931ac55f4cSDimitry Andric if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { 894bdd1243dSDimitry Andric // We are purposefully not using an allocator-aware default construction because the spec says so. 895bdd1243dSDimitry Andric // There's currently no way of expressing default initialization in an allocator-aware manner anyway. 896bdd1243dSDimitry Andric std::uninitialized_default_construct_n(std::begin(__data_), __count_); 8971ac55f4cSDimitry Andric } else { 8981ac55f4cSDimitry Andric std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::begin(__data_), __count_); 899bdd1243dSDimitry Andric } 9001ac55f4cSDimitry Andric # else 9011ac55f4cSDimitry Andric std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::begin(__data_), __count_); 902bdd1243dSDimitry Andric # endif 9031ac55f4cSDimitry Andric } 904bdd1243dSDimitry Andric 90581ad6265SDimitry Andric // Returns the number of bytes required to store a control block followed by the given number 90681ad6265SDimitry Andric // of elements of _Tp, with the whole storage being aligned to a multiple of _Tp's alignment. 907cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr size_t __bytes_for(size_t __elements) { 90881ad6265SDimitry Andric // When there's 0 elements, the control block alone is enough since it holds one element. 90981ad6265SDimitry Andric // Otherwise, we allocate one fewer element than requested because the control block already 91081ad6265SDimitry Andric // holds one. Also, we use the bitwise formula below to ensure that we allocate enough bytes 91181ad6265SDimitry Andric // for the whole allocation to be a multiple of _Tp's alignment. That formula is taken from [1]. 91281ad6265SDimitry Andric // 91381ad6265SDimitry Andric // [1]: https://en.wikipedia.org/wiki/Data_structure_alignment#Computing_padding 91481ad6265SDimitry Andric size_t __bytes = __elements == 0 ? sizeof(__unbounded_array_control_block) 91581ad6265SDimitry Andric : (__elements - 1) * sizeof(_Tp) + sizeof(__unbounded_array_control_block); 91681ad6265SDimitry Andric constexpr size_t __align = alignof(_Tp); 91781ad6265SDimitry Andric return (__bytes + __align - 1) & ~(__align - 1); 91881ad6265SDimitry Andric } 91981ad6265SDimitry Andric 920bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI_VIRTUAL 921cb14a3feSDimitry Andric ~__unbounded_array_control_block() override { 922cb14a3feSDimitry Andric } // can't be `= default` because of the sometimes-non-trivial union member __data_ 92381ad6265SDimitry Andric 92481ad6265SDimitry Andric private: 92506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override { 9261ac55f4cSDimitry Andric # if _LIBCPP_STD_VER >= 20 9271ac55f4cSDimitry Andric if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { 9281ac55f4cSDimitry Andric std::__reverse_destroy(__data_, __data_ + __count_); 9291ac55f4cSDimitry Andric } else { 93081ad6265SDimitry Andric __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); 93181ad6265SDimitry Andric std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + __count_); 93281ad6265SDimitry Andric } 9331ac55f4cSDimitry Andric # else 9341ac55f4cSDimitry Andric __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); 9351ac55f4cSDimitry Andric std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + __count_); 9361ac55f4cSDimitry Andric # endif 9371ac55f4cSDimitry Andric } 93881ad6265SDimitry Andric 93906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override { 94081ad6265SDimitry Andric using _AlignedStorage = __sp_aligned_storage<alignof(__unbounded_array_control_block)>; 94181ad6265SDimitry Andric using _StorageAlloc = __allocator_traits_rebind_t<_Alloc, _AlignedStorage>; 94281ad6265SDimitry Andric using _PointerTraits = pointer_traits<typename allocator_traits<_StorageAlloc>::pointer>; 94381ad6265SDimitry Andric 94481ad6265SDimitry Andric _StorageAlloc __tmp(__alloc_); 94581ad6265SDimitry Andric __alloc_.~_Alloc(); 94681ad6265SDimitry Andric size_t __size = __unbounded_array_control_block::__bytes_for(__count_); 94781ad6265SDimitry Andric _AlignedStorage* __storage = reinterpret_cast<_AlignedStorage*>(this); 9485c16e71dSDimitry Andric allocator_traits<_StorageAlloc>::deallocate( 9495c16e71dSDimitry Andric __tmp, _PointerTraits::pointer_to(*__storage), __size / sizeof(_AlignedStorage)); 95081ad6265SDimitry Andric } 95181ad6265SDimitry Andric 95281ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_; 95381ad6265SDimitry Andric size_t __count_; 95481ad6265SDimitry Andric union { 95581ad6265SDimitry Andric _Tp __data_[1]; 95681ad6265SDimitry Andric }; 95781ad6265SDimitry Andric }; 95881ad6265SDimitry Andric 95981ad6265SDimitry Andric template <class _Array, class _Alloc, class... _Arg> 960cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Array> 961cb14a3feSDimitry Andric __allocate_shared_unbounded_array(const _Alloc& __a, size_t __n, _Arg&&... __arg) { 96281ad6265SDimitry Andric static_assert(__libcpp_is_unbounded_array<_Array>::value); 96381ad6265SDimitry Andric // We compute the number of bytes necessary to hold the control block and the 96481ad6265SDimitry Andric // array elements. Then, we allocate an array of properly-aligned dummy structs 96581ad6265SDimitry Andric // large enough to hold the control block and array. This allows shifting the 96681ad6265SDimitry Andric // burden of aligning memory properly from us to the allocator. 96781ad6265SDimitry Andric using _ControlBlock = __unbounded_array_control_block<_Array, _Alloc>; 96881ad6265SDimitry Andric using _AlignedStorage = __sp_aligned_storage<alignof(_ControlBlock)>; 96981ad6265SDimitry Andric using _StorageAlloc = __allocator_traits_rebind_t<_Alloc, _AlignedStorage>; 97081ad6265SDimitry Andric __allocation_guard<_StorageAlloc> __guard(__a, _ControlBlock::__bytes_for(__n) / sizeof(_AlignedStorage)); 97181ad6265SDimitry Andric _ControlBlock* __control_block = reinterpret_cast<_ControlBlock*>(std::addressof(*__guard.__get())); 97281ad6265SDimitry Andric std::__construct_at(__control_block, __a, __n, std::forward<_Arg>(__arg)...); 97381ad6265SDimitry Andric __guard.__release_ptr(); 97481ad6265SDimitry Andric return shared_ptr<_Array>::__create_with_control_block(__control_block->__get_data(), __control_block); 97581ad6265SDimitry Andric } 97681ad6265SDimitry Andric 97781ad6265SDimitry Andric template <class _Tp, class _Alloc> 97881ad6265SDimitry Andric struct __bounded_array_control_block; 97981ad6265SDimitry Andric 98081ad6265SDimitry Andric template <class _Tp, size_t _Count, class _Alloc> 981cb14a3feSDimitry Andric struct __bounded_array_control_block<_Tp[_Count], _Alloc> : __shared_weak_count { 982cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp* __get_data() noexcept { return __data_; } 98381ad6265SDimitry Andric 984cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __bounded_array_control_block(_Alloc const& __alloc, _Tp const& __arg) 985cb14a3feSDimitry Andric : __alloc_(__alloc) { 9861ac55f4cSDimitry Andric std::__uninitialized_allocator_fill_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count, __arg); 98781ad6265SDimitry Andric } 98881ad6265SDimitry Andric 989cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit __bounded_array_control_block(_Alloc const& __alloc) : __alloc_(__alloc) { 990bdd1243dSDimitry Andric # if _LIBCPP_STD_VER >= 20 9911ac55f4cSDimitry Andric if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { 992bdd1243dSDimitry Andric // We are purposefully not using an allocator-aware default construction because the spec says so. 993bdd1243dSDimitry Andric // There's currently no way of expressing default initialization in an allocator-aware manner anyway. 994bdd1243dSDimitry Andric std::uninitialized_default_construct_n(std::addressof(__data_[0]), _Count); 9951ac55f4cSDimitry Andric } else { 9961ac55f4cSDimitry Andric std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count); 997bdd1243dSDimitry Andric } 9981ac55f4cSDimitry Andric # else 9991ac55f4cSDimitry Andric std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count); 1000bdd1243dSDimitry Andric # endif 10011ac55f4cSDimitry Andric } 1002bdd1243dSDimitry Andric 1003bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI_VIRTUAL 1004cb14a3feSDimitry Andric ~__bounded_array_control_block() override { 1005cb14a3feSDimitry Andric } // can't be `= default` because of the sometimes-non-trivial union member __data_ 100681ad6265SDimitry Andric 100781ad6265SDimitry Andric private: 100806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override { 10091ac55f4cSDimitry Andric # if _LIBCPP_STD_VER >= 20 10101ac55f4cSDimitry Andric if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) { 10111ac55f4cSDimitry Andric std::__reverse_destroy(__data_, __data_ + _Count); 10121ac55f4cSDimitry Andric } else { 101381ad6265SDimitry Andric __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); 101481ad6265SDimitry Andric std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + _Count); 101581ad6265SDimitry Andric } 10161ac55f4cSDimitry Andric # else 10171ac55f4cSDimitry Andric __allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_); 10181ac55f4cSDimitry Andric std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + _Count); 10191ac55f4cSDimitry Andric # endif 10201ac55f4cSDimitry Andric } 102181ad6265SDimitry Andric 102206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override { 102381ad6265SDimitry Andric using _ControlBlockAlloc = __allocator_traits_rebind_t<_Alloc, __bounded_array_control_block>; 102481ad6265SDimitry Andric using _PointerTraits = pointer_traits<typename allocator_traits<_ControlBlockAlloc>::pointer>; 102581ad6265SDimitry Andric 102681ad6265SDimitry Andric _ControlBlockAlloc __tmp(__alloc_); 102781ad6265SDimitry Andric __alloc_.~_Alloc(); 10285c16e71dSDimitry Andric allocator_traits<_ControlBlockAlloc>::deallocate(__tmp, _PointerTraits::pointer_to(*this), 1); 102981ad6265SDimitry Andric } 103081ad6265SDimitry Andric 103181ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc_; 103281ad6265SDimitry Andric union { 103381ad6265SDimitry Andric _Tp __data_[_Count]; 103481ad6265SDimitry Andric }; 103581ad6265SDimitry Andric }; 103681ad6265SDimitry Andric 103781ad6265SDimitry Andric template <class _Array, class _Alloc, class... _Arg> 1038cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Array> __allocate_shared_bounded_array(const _Alloc& __a, _Arg&&... __arg) { 103981ad6265SDimitry Andric static_assert(__libcpp_is_bounded_array<_Array>::value); 104081ad6265SDimitry Andric using _ControlBlock = __bounded_array_control_block<_Array, _Alloc>; 104181ad6265SDimitry Andric using _ControlBlockAlloc = __allocator_traits_rebind_t<_Alloc, _ControlBlock>; 104281ad6265SDimitry Andric 104381ad6265SDimitry Andric __allocation_guard<_ControlBlockAlloc> __guard(__a, 1); 104481ad6265SDimitry Andric _ControlBlock* __control_block = reinterpret_cast<_ControlBlock*>(std::addressof(*__guard.__get())); 104581ad6265SDimitry Andric std::__construct_at(__control_block, __a, std::forward<_Arg>(__arg)...); 104681ad6265SDimitry Andric __guard.__release_ptr(); 104781ad6265SDimitry Andric return shared_ptr<_Array>::__create_with_control_block(__control_block->__get_data(), __control_block); 104881ad6265SDimitry Andric } 104981ad6265SDimitry Andric 105006c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 17 105181ad6265SDimitry Andric 105206c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 105381ad6265SDimitry Andric 1054bdd1243dSDimitry Andric // bounded array variants 1055*0fca6ea1SDimitry Andric template <class _Tp, class _Alloc, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0> 1056cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a) { 105781ad6265SDimitry Andric return std::__allocate_shared_bounded_array<_Tp>(__a); 105881ad6265SDimitry Andric } 105981ad6265SDimitry Andric 1060*0fca6ea1SDimitry Andric template <class _Tp, class _Alloc, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0> 1061cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a, const remove_extent_t<_Tp>& __u) { 106281ad6265SDimitry Andric return std::__allocate_shared_bounded_array<_Tp>(__a, __u); 106381ad6265SDimitry Andric } 106481ad6265SDimitry Andric 1065bdd1243dSDimitry Andric template <class _Tp, class _Alloc, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0> 1066cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a) { 10671ac55f4cSDimitry Andric using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>; 10681ac55f4cSDimitry Andric _ForOverwriteAllocator __alloc(__a); 10691ac55f4cSDimitry Andric return std::__allocate_shared_bounded_array<_Tp>(__alloc); 107081ad6265SDimitry Andric } 107181ad6265SDimitry Andric 1072*0fca6ea1SDimitry Andric template <class _Tp, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0> 1073cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared() { 107481ad6265SDimitry Andric return std::__allocate_shared_bounded_array<_Tp>(allocator<_Tp>()); 107581ad6265SDimitry Andric } 107681ad6265SDimitry Andric 1077*0fca6ea1SDimitry Andric template <class _Tp, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0> 1078cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(const remove_extent_t<_Tp>& __u) { 107981ad6265SDimitry Andric return std::__allocate_shared_bounded_array<_Tp>(allocator<_Tp>(), __u); 108081ad6265SDimitry Andric } 108181ad6265SDimitry Andric 1082bdd1243dSDimitry Andric template <class _Tp, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0> 1083cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite() { 10841ac55f4cSDimitry Andric return std::__allocate_shared_bounded_array<_Tp>(allocator<__for_overwrite_tag>()); 1085bdd1243dSDimitry Andric } 1086bdd1243dSDimitry Andric 1087bdd1243dSDimitry Andric // unbounded array variants 1088*0fca6ea1SDimitry Andric template <class _Tp, class _Alloc, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0> 1089cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a, size_t __n) { 1090bdd1243dSDimitry Andric return std::__allocate_shared_unbounded_array<_Tp>(__a, __n); 1091bdd1243dSDimitry Andric } 1092bdd1243dSDimitry Andric 1093*0fca6ea1SDimitry Andric template <class _Tp, class _Alloc, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0> 1094cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared(const _Alloc& __a, size_t __n, const remove_extent_t<_Tp>& __u) { 1095bdd1243dSDimitry Andric return std::__allocate_shared_unbounded_array<_Tp>(__a, __n, __u); 1096bdd1243dSDimitry Andric } 1097bdd1243dSDimitry Andric 1098bdd1243dSDimitry Andric template <class _Tp, class _Alloc, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0> 1099cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a, size_t __n) { 11001ac55f4cSDimitry Andric using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>; 11011ac55f4cSDimitry Andric _ForOverwriteAllocator __alloc(__a); 11021ac55f4cSDimitry Andric return std::__allocate_shared_unbounded_array<_Tp>(__alloc, __n); 1103bdd1243dSDimitry Andric } 1104bdd1243dSDimitry Andric 1105*0fca6ea1SDimitry Andric template <class _Tp, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0> 1106cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(size_t __n) { 110781ad6265SDimitry Andric return std::__allocate_shared_unbounded_array<_Tp>(allocator<_Tp>(), __n); 110881ad6265SDimitry Andric } 110981ad6265SDimitry Andric 1110*0fca6ea1SDimitry Andric template <class _Tp, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0> 1111cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared(size_t __n, const remove_extent_t<_Tp>& __u) { 111281ad6265SDimitry Andric return std::__allocate_shared_unbounded_array<_Tp>(allocator<_Tp>(), __n, __u); 111381ad6265SDimitry Andric } 111481ad6265SDimitry Andric 1115bdd1243dSDimitry Andric template <class _Tp, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0> 1116cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> make_shared_for_overwrite(size_t __n) { 11171ac55f4cSDimitry Andric return std::__allocate_shared_unbounded_array<_Tp>(allocator<__for_overwrite_tag>(), __n); 1118bdd1243dSDimitry Andric } 1119bdd1243dSDimitry Andric 112006c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20 112181ad6265SDimitry Andric 1122fe6060f1SDimitry Andric template <class _Tp, class _Up> 1123cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator==(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT { 1124fe6060f1SDimitry Andric return __x.get() == __y.get(); 1125fe6060f1SDimitry Andric } 1126fe6060f1SDimitry Andric 1127bdd1243dSDimitry Andric #if _LIBCPP_STD_VER <= 17 1128bdd1243dSDimitry Andric 1129fe6060f1SDimitry Andric template <class _Tp, class _Up> 1130cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT { 1131fe6060f1SDimitry Andric return !(__x == __y); 1132fe6060f1SDimitry Andric } 1133fe6060f1SDimitry Andric 1134fe6060f1SDimitry Andric template <class _Tp, class _Up> 1135cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator<(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT { 1136fe6060f1SDimitry Andric # if _LIBCPP_STD_VER <= 11 1137fe6060f1SDimitry Andric typedef typename common_type<_Tp*, _Up*>::type _Vp; 1138fe6060f1SDimitry Andric return less<_Vp>()(__x.get(), __y.get()); 1139fe6060f1SDimitry Andric # else 1140fe6060f1SDimitry Andric return less<>()(__x.get(), __y.get()); 1141fe6060f1SDimitry Andric # endif 1142fe6060f1SDimitry Andric } 1143fe6060f1SDimitry Andric 1144fe6060f1SDimitry Andric template <class _Tp, class _Up> 1145cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator>(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT { 1146fe6060f1SDimitry Andric return __y < __x; 1147fe6060f1SDimitry Andric } 1148fe6060f1SDimitry Andric 1149fe6060f1SDimitry Andric template <class _Tp, class _Up> 1150cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT { 1151fe6060f1SDimitry Andric return !(__y < __x); 1152fe6060f1SDimitry Andric } 1153fe6060f1SDimitry Andric 1154fe6060f1SDimitry Andric template <class _Tp, class _Up> 1155cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const shared_ptr<_Tp>& __x, const shared_ptr<_Up>& __y) _NOEXCEPT { 1156fe6060f1SDimitry Andric return !(__x < __y); 1157fe6060f1SDimitry Andric } 1158fe6060f1SDimitry Andric 1159bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER <= 17 1160bdd1243dSDimitry Andric 116106c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 1162bdd1243dSDimitry Andric template <class _Tp, class _Up> 1163cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(shared_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) noexcept { 1164bdd1243dSDimitry Andric return compare_three_way()(__x.get(), __y.get()); 1165bdd1243dSDimitry Andric } 1166bdd1243dSDimitry Andric #endif 1167bdd1243dSDimitry Andric 1168fe6060f1SDimitry Andric template <class _Tp> 1169cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator==(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT { 1170fe6060f1SDimitry Andric return !__x; 1171fe6060f1SDimitry Andric } 1172fe6060f1SDimitry Andric 1173bdd1243dSDimitry Andric #if _LIBCPP_STD_VER <= 17 1174bdd1243dSDimitry Andric 1175fe6060f1SDimitry Andric template <class _Tp> 1176cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator==(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT { 1177fe6060f1SDimitry Andric return !__x; 1178fe6060f1SDimitry Andric } 1179fe6060f1SDimitry Andric 1180fe6060f1SDimitry Andric template <class _Tp> 1181cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT { 1182fe6060f1SDimitry Andric return static_cast<bool>(__x); 1183fe6060f1SDimitry Andric } 1184fe6060f1SDimitry Andric 1185fe6060f1SDimitry Andric template <class _Tp> 1186cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator!=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT { 1187fe6060f1SDimitry Andric return static_cast<bool>(__x); 1188fe6060f1SDimitry Andric } 1189fe6060f1SDimitry Andric 1190fe6060f1SDimitry Andric template <class _Tp> 1191cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator<(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT { 1192297eecfbSDimitry Andric return less<typename shared_ptr<_Tp>::element_type*>()(__x.get(), nullptr); 1193fe6060f1SDimitry Andric } 1194fe6060f1SDimitry Andric 1195fe6060f1SDimitry Andric template <class _Tp> 1196cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator<(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT { 1197297eecfbSDimitry Andric return less<typename shared_ptr<_Tp>::element_type*>()(nullptr, __x.get()); 1198fe6060f1SDimitry Andric } 1199fe6060f1SDimitry Andric 1200fe6060f1SDimitry Andric template <class _Tp> 1201cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator>(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT { 1202fe6060f1SDimitry Andric return nullptr < __x; 1203fe6060f1SDimitry Andric } 1204fe6060f1SDimitry Andric 1205fe6060f1SDimitry Andric template <class _Tp> 1206cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator>(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT { 1207fe6060f1SDimitry Andric return __x < nullptr; 1208fe6060f1SDimitry Andric } 1209fe6060f1SDimitry Andric 1210fe6060f1SDimitry Andric template <class _Tp> 1211cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT { 1212fe6060f1SDimitry Andric return !(nullptr < __x); 1213fe6060f1SDimitry Andric } 1214fe6060f1SDimitry Andric 1215fe6060f1SDimitry Andric template <class _Tp> 1216cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator<=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT { 1217fe6060f1SDimitry Andric return !(__x < nullptr); 1218fe6060f1SDimitry Andric } 1219fe6060f1SDimitry Andric 1220fe6060f1SDimitry Andric template <class _Tp> 1221cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const shared_ptr<_Tp>& __x, nullptr_t) _NOEXCEPT { 1222fe6060f1SDimitry Andric return !(__x < nullptr); 1223fe6060f1SDimitry Andric } 1224fe6060f1SDimitry Andric 1225fe6060f1SDimitry Andric template <class _Tp> 1226cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool operator>=(nullptr_t, const shared_ptr<_Tp>& __x) _NOEXCEPT { 1227fe6060f1SDimitry Andric return !(nullptr < __x); 1228fe6060f1SDimitry Andric } 1229fe6060f1SDimitry Andric 1230bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER <= 17 1231bdd1243dSDimitry Andric 123206c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 1233bdd1243dSDimitry Andric template <class _Tp> 1234cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI strong_ordering operator<=>(shared_ptr<_Tp> const& __x, nullptr_t) noexcept { 1235bdd1243dSDimitry Andric return compare_three_way()(__x.get(), static_cast<typename shared_ptr<_Tp>::element_type*>(nullptr)); 1236bdd1243dSDimitry Andric } 1237bdd1243dSDimitry Andric #endif 1238bdd1243dSDimitry Andric 1239fe6060f1SDimitry Andric template <class _Tp> 1240cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI void swap(shared_ptr<_Tp>& __x, shared_ptr<_Tp>& __y) _NOEXCEPT { 1241fe6060f1SDimitry Andric __x.swap(__y); 1242fe6060f1SDimitry Andric } 1243fe6060f1SDimitry Andric 1244fe6060f1SDimitry Andric template <class _Tp, class _Up> 1245cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> static_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT { 1246cb14a3feSDimitry Andric return shared_ptr<_Tp>(__r, static_cast< typename shared_ptr<_Tp>::element_type*>(__r.get())); 1247fe6060f1SDimitry Andric } 1248fe6060f1SDimitry Andric 124906c3fb27SDimitry Andric // LWG-2996 125006c3fb27SDimitry Andric // We don't backport because it is an evolutionary change. 125106c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 125206c3fb27SDimitry Andric template <class _Tp, class _Up> 125306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> static_pointer_cast(shared_ptr<_Up>&& __r) noexcept { 125406c3fb27SDimitry Andric return shared_ptr<_Tp>(std::move(__r), static_cast<typename shared_ptr<_Tp>::element_type*>(__r.get())); 125506c3fb27SDimitry Andric } 125606c3fb27SDimitry Andric #endif 125706c3fb27SDimitry Andric 1258fe6060f1SDimitry Andric template <class _Tp, class _Up> 1259cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> dynamic_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT { 1260fe6060f1SDimitry Andric typedef typename shared_ptr<_Tp>::element_type _ET; 1261fe6060f1SDimitry Andric _ET* __p = dynamic_cast<_ET*>(__r.get()); 1262fe6060f1SDimitry Andric return __p ? shared_ptr<_Tp>(__r, __p) : shared_ptr<_Tp>(); 1263fe6060f1SDimitry Andric } 1264fe6060f1SDimitry Andric 126506c3fb27SDimitry Andric // LWG-2996 126606c3fb27SDimitry Andric // We don't backport because it is an evolutionary change. 126706c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 126806c3fb27SDimitry Andric template <class _Tp, class _Up> 126906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> dynamic_pointer_cast(shared_ptr<_Up>&& __r) noexcept { 127006c3fb27SDimitry Andric auto* __p = dynamic_cast<typename shared_ptr<_Tp>::element_type*>(__r.get()); 127106c3fb27SDimitry Andric return __p ? shared_ptr<_Tp>(std::move(__r), __p) : shared_ptr<_Tp>(); 127206c3fb27SDimitry Andric } 127306c3fb27SDimitry Andric #endif 127406c3fb27SDimitry Andric 1275fe6060f1SDimitry Andric template <class _Tp, class _Up> 1276cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> const_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT { 1277fe6060f1SDimitry Andric typedef typename shared_ptr<_Tp>::element_type _RTp; 1278fe6060f1SDimitry Andric return shared_ptr<_Tp>(__r, const_cast<_RTp*>(__r.get())); 1279fe6060f1SDimitry Andric } 1280fe6060f1SDimitry Andric 128106c3fb27SDimitry Andric // LWG-2996 128206c3fb27SDimitry Andric // We don't backport because it is an evolutionary change. 128306c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 128406c3fb27SDimitry Andric template <class _Tp, class _Up> 128506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> const_pointer_cast(shared_ptr<_Up>&& __r) noexcept { 128606c3fb27SDimitry Andric return shared_ptr<_Tp>(std::move(__r), const_cast<typename shared_ptr<_Tp>::element_type*>(__r.get())); 128706c3fb27SDimitry Andric } 128806c3fb27SDimitry Andric #endif 128906c3fb27SDimitry Andric 1290fe6060f1SDimitry Andric template <class _Tp, class _Up> 1291cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT { 1292cb14a3feSDimitry Andric return shared_ptr<_Tp>(__r, reinterpret_cast< typename shared_ptr<_Tp>::element_type*>(__r.get())); 1293fe6060f1SDimitry Andric } 1294fe6060f1SDimitry Andric 129506c3fb27SDimitry Andric // LWG-2996 129606c3fb27SDimitry Andric // We don't backport because it is an evolutionary change. 129706c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 129806c3fb27SDimitry Andric template <class _Tp, class _Up> 129906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> reinterpret_pointer_cast(shared_ptr<_Up>&& __r) noexcept { 130006c3fb27SDimitry Andric return shared_ptr<_Tp>(std::move(__r), reinterpret_cast<typename shared_ptr<_Tp>::element_type*>(__r.get())); 130106c3fb27SDimitry Andric } 130206c3fb27SDimitry Andric #endif 130306c3fb27SDimitry Andric 13041ac55f4cSDimitry Andric #ifndef _LIBCPP_HAS_NO_RTTI 1305fe6060f1SDimitry Andric 1306fe6060f1SDimitry Andric template <class _Dp, class _Tp> 1307cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _Dp* get_deleter(const shared_ptr<_Tp>& __p) _NOEXCEPT { 1308fe6060f1SDimitry Andric return __p.template __get_deleter<_Dp>(); 1309fe6060f1SDimitry Andric } 1310fe6060f1SDimitry Andric 13111ac55f4cSDimitry Andric #endif // _LIBCPP_HAS_NO_RTTI 1312fe6060f1SDimitry Andric 1313fe6060f1SDimitry Andric template <class _Tp> 1314cb14a3feSDimitry Andric class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr { 1315fe6060f1SDimitry Andric public: 131606c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17 1317349cc55cSDimitry Andric typedef remove_extent_t<_Tp> element_type; 1318349cc55cSDimitry Andric #else 1319fe6060f1SDimitry Andric typedef _Tp element_type; 1320349cc55cSDimitry Andric #endif 1321349cc55cSDimitry Andric 1322*0fca6ea1SDimitry Andric // A weak_ptr contains only two raw pointers which point to the heap and move constructing already doesn't require 1323*0fca6ea1SDimitry Andric // any bookkeeping, so it's always trivially relocatable. 1324*0fca6ea1SDimitry Andric using __trivially_relocatable = weak_ptr; 1325*0fca6ea1SDimitry Andric 1326fe6060f1SDimitry Andric private: 1327fe6060f1SDimitry Andric element_type* __ptr_; 1328fe6060f1SDimitry Andric __shared_weak_count* __cntrl_; 1329fe6060f1SDimitry Andric 1330fe6060f1SDimitry Andric public: 1331cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR weak_ptr() _NOEXCEPT; 1332fe6060f1SDimitry Andric 13335f757f3fSDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> = 0> 13345f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI weak_ptr(shared_ptr<_Yp> const& __r) _NOEXCEPT; 13355f757f3fSDimitry Andric 1336cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI weak_ptr(weak_ptr const& __r) _NOEXCEPT; 13375f757f3fSDimitry Andric 13385f757f3fSDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> = 0> 13395f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI weak_ptr(weak_ptr<_Yp> const& __r) _NOEXCEPT; 13405f757f3fSDimitry Andric 1341cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI weak_ptr(weak_ptr&& __r) _NOEXCEPT; 13425f757f3fSDimitry Andric 13435f757f3fSDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> = 0> 13445f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI weak_ptr(weak_ptr<_Yp>&& __r) _NOEXCEPT; 13455f757f3fSDimitry Andric 134606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI ~weak_ptr(); 1347fe6060f1SDimitry Andric 1348cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI weak_ptr& operator=(weak_ptr const& __r) _NOEXCEPT; 13495f757f3fSDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> = 0> 1350cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI weak_ptr& operator=(weak_ptr<_Yp> const& __r) _NOEXCEPT; 1351fe6060f1SDimitry Andric 1352cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI weak_ptr& operator=(weak_ptr&& __r) _NOEXCEPT; 13535f757f3fSDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> = 0> 1354cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI weak_ptr& operator=(weak_ptr<_Yp>&& __r) _NOEXCEPT; 1355fe6060f1SDimitry Andric 13565f757f3fSDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> = 0> 1357cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI weak_ptr& operator=(shared_ptr<_Yp> const& __r) _NOEXCEPT; 1358fe6060f1SDimitry Andric 1359cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void swap(weak_ptr& __r) _NOEXCEPT; 1360cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void reset() _NOEXCEPT; 1361fe6060f1SDimitry Andric 1362cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI long use_count() const _NOEXCEPT { return __cntrl_ ? __cntrl_->use_count() : 0; } 1363cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool expired() const _NOEXCEPT { return __cntrl_ == nullptr || __cntrl_->use_count() == 0; } 136406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> lock() const _NOEXCEPT; 1365fe6060f1SDimitry Andric template <class _Up> 1366cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool owner_before(const shared_ptr<_Up>& __r) const _NOEXCEPT { 1367cb14a3feSDimitry Andric return __cntrl_ < __r.__cntrl_; 1368cb14a3feSDimitry Andric } 1369fe6060f1SDimitry Andric template <class _Up> 1370cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool owner_before(const weak_ptr<_Up>& __r) const _NOEXCEPT { 1371cb14a3feSDimitry Andric return __cntrl_ < __r.__cntrl_; 1372cb14a3feSDimitry Andric } 1373fe6060f1SDimitry Andric 1374cb14a3feSDimitry Andric template <class _Up> 1375cb14a3feSDimitry Andric friend class _LIBCPP_TEMPLATE_VIS weak_ptr; 1376cb14a3feSDimitry Andric template <class _Up> 1377cb14a3feSDimitry Andric friend class _LIBCPP_TEMPLATE_VIS shared_ptr; 1378fe6060f1SDimitry Andric }; 1379fe6060f1SDimitry Andric 138006c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17 1381fe6060f1SDimitry Andric template <class _Tp> 1382fe6060f1SDimitry Andric weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>; 1383fe6060f1SDimitry Andric #endif 1384fe6060f1SDimitry Andric 1385fe6060f1SDimitry Andric template <class _Tp> 1386cb14a3feSDimitry Andric inline _LIBCPP_CONSTEXPR weak_ptr<_Tp>::weak_ptr() _NOEXCEPT : __ptr_(nullptr), __cntrl_(nullptr) {} 1387fe6060f1SDimitry Andric 1388fe6060f1SDimitry Andric template <class _Tp> 1389cb14a3feSDimitry Andric inline weak_ptr<_Tp>::weak_ptr(weak_ptr const& __r) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_) { 1390fe6060f1SDimitry Andric if (__cntrl_) 1391fe6060f1SDimitry Andric __cntrl_->__add_weak(); 1392fe6060f1SDimitry Andric } 1393fe6060f1SDimitry Andric 1394fe6060f1SDimitry Andric template <class _Tp> 13955f757f3fSDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> > 1396cb14a3feSDimitry Andric inline weak_ptr<_Tp>::weak_ptr(shared_ptr<_Yp> const& __r) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_) { 1397fe6060f1SDimitry Andric if (__cntrl_) 1398fe6060f1SDimitry Andric __cntrl_->__add_weak(); 1399fe6060f1SDimitry Andric } 1400fe6060f1SDimitry Andric 1401fe6060f1SDimitry Andric template <class _Tp> 14025f757f3fSDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> > 1403cb14a3feSDimitry Andric inline weak_ptr<_Tp>::weak_ptr(weak_ptr<_Yp> const& __r) _NOEXCEPT : __ptr_(nullptr), __cntrl_(nullptr) { 14045f757f3fSDimitry Andric shared_ptr<_Yp> __s = __r.lock(); 14055f757f3fSDimitry Andric *this = weak_ptr<_Tp>(__s); 1406fe6060f1SDimitry Andric } 1407fe6060f1SDimitry Andric 1408fe6060f1SDimitry Andric template <class _Tp> 1409cb14a3feSDimitry Andric inline weak_ptr<_Tp>::weak_ptr(weak_ptr&& __r) _NOEXCEPT : __ptr_(__r.__ptr_), __cntrl_(__r.__cntrl_) { 1410fe6060f1SDimitry Andric __r.__ptr_ = nullptr; 1411fe6060f1SDimitry Andric __r.__cntrl_ = nullptr; 1412fe6060f1SDimitry Andric } 1413fe6060f1SDimitry Andric 1414fe6060f1SDimitry Andric template <class _Tp> 14155f757f3fSDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> > 1416cb14a3feSDimitry Andric inline weak_ptr<_Tp>::weak_ptr(weak_ptr<_Yp>&& __r) _NOEXCEPT : __ptr_(nullptr), __cntrl_(nullptr) { 14175f757f3fSDimitry Andric shared_ptr<_Yp> __s = __r.lock(); 14185f757f3fSDimitry Andric *this = weak_ptr<_Tp>(__s); 14195f757f3fSDimitry Andric __r.reset(); 1420fe6060f1SDimitry Andric } 1421fe6060f1SDimitry Andric 1422fe6060f1SDimitry Andric template <class _Tp> 1423cb14a3feSDimitry Andric weak_ptr<_Tp>::~weak_ptr() { 1424fe6060f1SDimitry Andric if (__cntrl_) 1425fe6060f1SDimitry Andric __cntrl_->__release_weak(); 1426fe6060f1SDimitry Andric } 1427fe6060f1SDimitry Andric 1428fe6060f1SDimitry Andric template <class _Tp> 1429cb14a3feSDimitry Andric inline weak_ptr<_Tp>& weak_ptr<_Tp>::operator=(weak_ptr const& __r) _NOEXCEPT { 1430fe6060f1SDimitry Andric weak_ptr(__r).swap(*this); 1431fe6060f1SDimitry Andric return *this; 1432fe6060f1SDimitry Andric } 1433fe6060f1SDimitry Andric 1434fe6060f1SDimitry Andric template <class _Tp> 14355f757f3fSDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> > 1436cb14a3feSDimitry Andric inline weak_ptr<_Tp>& weak_ptr<_Tp>::operator=(weak_ptr<_Yp> const& __r) _NOEXCEPT { 1437fe6060f1SDimitry Andric weak_ptr(__r).swap(*this); 1438fe6060f1SDimitry Andric return *this; 1439fe6060f1SDimitry Andric } 1440fe6060f1SDimitry Andric 1441fe6060f1SDimitry Andric template <class _Tp> 1442cb14a3feSDimitry Andric inline weak_ptr<_Tp>& weak_ptr<_Tp>::operator=(weak_ptr&& __r) _NOEXCEPT { 14435f757f3fSDimitry Andric weak_ptr(std::move(__r)).swap(*this); 1444fe6060f1SDimitry Andric return *this; 1445fe6060f1SDimitry Andric } 1446fe6060f1SDimitry Andric 1447fe6060f1SDimitry Andric template <class _Tp> 14485f757f3fSDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> > 1449cb14a3feSDimitry Andric inline weak_ptr<_Tp>& weak_ptr<_Tp>::operator=(weak_ptr<_Yp>&& __r) _NOEXCEPT { 14505f757f3fSDimitry Andric weak_ptr(std::move(__r)).swap(*this); 1451fe6060f1SDimitry Andric return *this; 1452fe6060f1SDimitry Andric } 1453fe6060f1SDimitry Andric 1454fe6060f1SDimitry Andric template <class _Tp> 14555f757f3fSDimitry Andric template <class _Yp, __enable_if_t<__compatible_with<_Yp, _Tp>::value, int> > 1456cb14a3feSDimitry Andric inline weak_ptr<_Tp>& weak_ptr<_Tp>::operator=(shared_ptr<_Yp> const& __r) _NOEXCEPT { 1457fe6060f1SDimitry Andric weak_ptr(__r).swap(*this); 1458fe6060f1SDimitry Andric return *this; 1459fe6060f1SDimitry Andric } 1460fe6060f1SDimitry Andric 1461fe6060f1SDimitry Andric template <class _Tp> 1462cb14a3feSDimitry Andric inline void weak_ptr<_Tp>::swap(weak_ptr& __r) _NOEXCEPT { 14635f757f3fSDimitry Andric std::swap(__ptr_, __r.__ptr_); 14645f757f3fSDimitry Andric std::swap(__cntrl_, __r.__cntrl_); 1465fe6060f1SDimitry Andric } 1466fe6060f1SDimitry Andric 1467fe6060f1SDimitry Andric template <class _Tp> 1468cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI void swap(weak_ptr<_Tp>& __x, weak_ptr<_Tp>& __y) _NOEXCEPT { 1469fe6060f1SDimitry Andric __x.swap(__y); 1470fe6060f1SDimitry Andric } 1471fe6060f1SDimitry Andric 1472fe6060f1SDimitry Andric template <class _Tp> 1473cb14a3feSDimitry Andric inline void weak_ptr<_Tp>::reset() _NOEXCEPT { 1474fe6060f1SDimitry Andric weak_ptr().swap(*this); 1475fe6060f1SDimitry Andric } 1476fe6060f1SDimitry Andric 1477fe6060f1SDimitry Andric template <class _Tp> 1478cb14a3feSDimitry Andric shared_ptr<_Tp> weak_ptr<_Tp>::lock() const _NOEXCEPT { 1479fe6060f1SDimitry Andric shared_ptr<_Tp> __r; 1480fe6060f1SDimitry Andric __r.__cntrl_ = __cntrl_ ? __cntrl_->lock() : __cntrl_; 1481fe6060f1SDimitry Andric if (__r.__cntrl_) 1482fe6060f1SDimitry Andric __r.__ptr_ = __ptr_; 1483fe6060f1SDimitry Andric return __r; 1484fe6060f1SDimitry Andric } 1485fe6060f1SDimitry Andric 148606c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17 1487cb14a3feSDimitry Andric template <class _Tp = void> 1488cb14a3feSDimitry Andric struct owner_less; 1489fe6060f1SDimitry Andric #else 1490cb14a3feSDimitry Andric template <class _Tp> 1491cb14a3feSDimitry Andric struct owner_less; 1492fe6060f1SDimitry Andric #endif 1493fe6060f1SDimitry Andric 1494fe6060f1SDimitry Andric template <class _Tp> 1495cb14a3feSDimitry Andric struct _LIBCPP_TEMPLATE_VIS owner_less<shared_ptr<_Tp> > : __binary_function<shared_ptr<_Tp>, shared_ptr<_Tp>, bool> { 1496cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool operator()(shared_ptr<_Tp> const& __x, shared_ptr<_Tp> const& __y) const _NOEXCEPT { 1497cb14a3feSDimitry Andric return __x.owner_before(__y); 1498cb14a3feSDimitry Andric } 1499cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool operator()(shared_ptr<_Tp> const& __x, weak_ptr<_Tp> const& __y) const _NOEXCEPT { 1500cb14a3feSDimitry Andric return __x.owner_before(__y); 1501cb14a3feSDimitry Andric } 1502cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool operator()(weak_ptr<_Tp> const& __x, shared_ptr<_Tp> const& __y) const _NOEXCEPT { 1503cb14a3feSDimitry Andric return __x.owner_before(__y); 1504cb14a3feSDimitry Andric } 1505fe6060f1SDimitry Andric }; 1506fe6060f1SDimitry Andric 1507fe6060f1SDimitry Andric template <class _Tp> 1508cb14a3feSDimitry Andric struct _LIBCPP_TEMPLATE_VIS owner_less<weak_ptr<_Tp> > : __binary_function<weak_ptr<_Tp>, weak_ptr<_Tp>, bool> { 1509cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool operator()(weak_ptr<_Tp> const& __x, weak_ptr<_Tp> const& __y) const _NOEXCEPT { 1510cb14a3feSDimitry Andric return __x.owner_before(__y); 1511cb14a3feSDimitry Andric } 1512cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool operator()(shared_ptr<_Tp> const& __x, weak_ptr<_Tp> const& __y) const _NOEXCEPT { 1513cb14a3feSDimitry Andric return __x.owner_before(__y); 1514cb14a3feSDimitry Andric } 1515cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool operator()(weak_ptr<_Tp> const& __x, shared_ptr<_Tp> const& __y) const _NOEXCEPT { 1516cb14a3feSDimitry Andric return __x.owner_before(__y); 1517cb14a3feSDimitry Andric } 1518fe6060f1SDimitry Andric }; 1519fe6060f1SDimitry Andric 152006c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17 1521fe6060f1SDimitry Andric template <> 1522cb14a3feSDimitry Andric struct _LIBCPP_TEMPLATE_VIS owner_less<void> { 1523fe6060f1SDimitry Andric template <class _Tp, class _Up> 1524cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool operator()(shared_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) const _NOEXCEPT { 1525cb14a3feSDimitry Andric return __x.owner_before(__y); 1526cb14a3feSDimitry Andric } 1527fe6060f1SDimitry Andric template <class _Tp, class _Up> 1528cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool operator()(shared_ptr<_Tp> const& __x, weak_ptr<_Up> const& __y) const _NOEXCEPT { 1529cb14a3feSDimitry Andric return __x.owner_before(__y); 1530cb14a3feSDimitry Andric } 1531fe6060f1SDimitry Andric template <class _Tp, class _Up> 1532cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool operator()(weak_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) const _NOEXCEPT { 1533cb14a3feSDimitry Andric return __x.owner_before(__y); 1534cb14a3feSDimitry Andric } 1535fe6060f1SDimitry Andric template <class _Tp, class _Up> 1536cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool operator()(weak_ptr<_Tp> const& __x, weak_ptr<_Up> const& __y) const _NOEXCEPT { 1537cb14a3feSDimitry Andric return __x.owner_before(__y); 1538cb14a3feSDimitry Andric } 1539fe6060f1SDimitry Andric typedef void is_transparent; 1540fe6060f1SDimitry Andric }; 1541fe6060f1SDimitry Andric #endif 1542fe6060f1SDimitry Andric 1543fe6060f1SDimitry Andric template <class _Tp> 1544cb14a3feSDimitry Andric class _LIBCPP_TEMPLATE_VIS enable_shared_from_this { 1545fe6060f1SDimitry Andric mutable weak_ptr<_Tp> __weak_this_; 1546cb14a3feSDimitry Andric 1547fe6060f1SDimitry Andric protected: 1548cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR enable_shared_from_this() _NOEXCEPT {} 1549cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI enable_shared_from_this(enable_shared_from_this const&) _NOEXCEPT {} 1550cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI enable_shared_from_this& operator=(enable_shared_from_this const&) _NOEXCEPT { return *this; } 1551cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI ~enable_shared_from_this() {} 1552cb14a3feSDimitry Andric 1553fe6060f1SDimitry Andric public: 1554cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> shared_from_this() { return shared_ptr<_Tp>(__weak_this_); } 1555cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp const> shared_from_this() const { return shared_ptr<const _Tp>(__weak_this_); } 1556fe6060f1SDimitry Andric 155706c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17 1558cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI weak_ptr<_Tp> weak_from_this() _NOEXCEPT { return __weak_this_; } 1559fe6060f1SDimitry Andric 1560cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI weak_ptr<const _Tp> weak_from_this() const _NOEXCEPT { return __weak_this_; } 156106c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 17 1562fe6060f1SDimitry Andric 1563cb14a3feSDimitry Andric template <class _Up> 1564cb14a3feSDimitry Andric friend class shared_ptr; 1565fe6060f1SDimitry Andric }; 1566fe6060f1SDimitry Andric 1567cb14a3feSDimitry Andric template <class _Tp> 1568cb14a3feSDimitry Andric struct _LIBCPP_TEMPLATE_VIS hash; 1569fe6060f1SDimitry Andric 1570fe6060f1SDimitry Andric template <class _Tp> 1571cb14a3feSDimitry Andric struct _LIBCPP_TEMPLATE_VIS hash<shared_ptr<_Tp> > { 1572fe6060f1SDimitry Andric #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS) 1573fe6060f1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX17 typedef shared_ptr<_Tp> argument_type; 1574fe6060f1SDimitry Andric _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type; 1575fe6060f1SDimitry Andric #endif 1576fe6060f1SDimitry Andric 1577cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI size_t operator()(const shared_ptr<_Tp>& __ptr) const _NOEXCEPT { 1578fe6060f1SDimitry Andric return hash<typename shared_ptr<_Tp>::element_type*>()(__ptr.get()); 1579fe6060f1SDimitry Andric } 1580fe6060f1SDimitry Andric }; 1581fe6060f1SDimitry Andric 1582fe6060f1SDimitry Andric template <class _CharT, class _Traits, class _Yp> 1583cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 1584fe6060f1SDimitry Andric operator<<(basic_ostream<_CharT, _Traits>& __os, shared_ptr<_Yp> const& __p); 1585fe6060f1SDimitry Andric 1586349cc55cSDimitry Andric #if !defined(_LIBCPP_HAS_NO_THREADS) 1587fe6060f1SDimitry Andric 1588cb14a3feSDimitry Andric class _LIBCPP_EXPORTED_FROM_ABI __sp_mut { 1589bdd1243dSDimitry Andric void* __lx_; 1590cb14a3feSDimitry Andric 1591fe6060f1SDimitry Andric public: 1592fe6060f1SDimitry Andric void lock() _NOEXCEPT; 1593fe6060f1SDimitry Andric void unlock() _NOEXCEPT; 1594fe6060f1SDimitry Andric 1595fe6060f1SDimitry Andric private: 1596fe6060f1SDimitry Andric _LIBCPP_CONSTEXPR __sp_mut(void*) _NOEXCEPT; 1597fe6060f1SDimitry Andric __sp_mut(const __sp_mut&); 1598fe6060f1SDimitry Andric __sp_mut& operator=(const __sp_mut&); 1599fe6060f1SDimitry Andric 160006c3fb27SDimitry Andric friend _LIBCPP_EXPORTED_FROM_ABI __sp_mut& __get_sp_mut(const void*); 1601fe6060f1SDimitry Andric }; 1602fe6060f1SDimitry Andric 16035f757f3fSDimitry Andric _LIBCPP_EXPORTED_FROM_ABI __sp_mut& __get_sp_mut(const void*); 1604fe6060f1SDimitry Andric 1605fe6060f1SDimitry Andric template <class _Tp> 1606cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const shared_ptr<_Tp>*) { 1607fe6060f1SDimitry Andric return false; 1608fe6060f1SDimitry Andric } 1609fe6060f1SDimitry Andric 1610fe6060f1SDimitry Andric template <class _Tp> 1611cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> atomic_load(const shared_ptr<_Tp>* __p) { 1612bdd1243dSDimitry Andric __sp_mut& __m = std::__get_sp_mut(__p); 1613fe6060f1SDimitry Andric __m.lock(); 1614fe6060f1SDimitry Andric shared_ptr<_Tp> __q = *__p; 1615fe6060f1SDimitry Andric __m.unlock(); 1616fe6060f1SDimitry Andric return __q; 1617fe6060f1SDimitry Andric } 1618fe6060f1SDimitry Andric 1619fe6060f1SDimitry Andric template <class _Tp> 1620cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order) { 1621bdd1243dSDimitry Andric return std::atomic_load(__p); 1622fe6060f1SDimitry Andric } 1623fe6060f1SDimitry Andric 1624fe6060f1SDimitry Andric template <class _Tp> 1625cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r) { 1626bdd1243dSDimitry Andric __sp_mut& __m = std::__get_sp_mut(__p); 1627fe6060f1SDimitry Andric __m.lock(); 1628fe6060f1SDimitry Andric __p->swap(__r); 1629fe6060f1SDimitry Andric __m.unlock(); 1630fe6060f1SDimitry Andric } 1631fe6060f1SDimitry Andric 1632fe6060f1SDimitry Andric template <class _Tp> 1633cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI void atomic_store_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, memory_order) { 1634bdd1243dSDimitry Andric std::atomic_store(__p, __r); 1635fe6060f1SDimitry Andric } 1636fe6060f1SDimitry Andric 1637fe6060f1SDimitry Andric template <class _Tp> 1638cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r) { 1639bdd1243dSDimitry Andric __sp_mut& __m = std::__get_sp_mut(__p); 1640fe6060f1SDimitry Andric __m.lock(); 1641fe6060f1SDimitry Andric __p->swap(__r); 1642fe6060f1SDimitry Andric __m.unlock(); 1643fe6060f1SDimitry Andric return __r; 1644fe6060f1SDimitry Andric } 1645fe6060f1SDimitry Andric 1646fe6060f1SDimitry Andric template <class _Tp> 1647cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI shared_ptr<_Tp> 1648cb14a3feSDimitry Andric atomic_exchange_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r, memory_order) { 1649bdd1243dSDimitry Andric return std::atomic_exchange(__p, __r); 1650fe6060f1SDimitry Andric } 1651fe6060f1SDimitry Andric 1652fe6060f1SDimitry Andric template <class _Tp> 1653bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI bool 1654cb14a3feSDimitry Andric atomic_compare_exchange_strong(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_ptr<_Tp> __w) { 1655fe6060f1SDimitry Andric shared_ptr<_Tp> __temp; 1656bdd1243dSDimitry Andric __sp_mut& __m = std::__get_sp_mut(__p); 1657fe6060f1SDimitry Andric __m.lock(); 1658cb14a3feSDimitry Andric if (__p->__owner_equivalent(*__v)) { 16595f757f3fSDimitry Andric std::swap(__temp, *__p); 1660fe6060f1SDimitry Andric *__p = __w; 1661fe6060f1SDimitry Andric __m.unlock(); 1662fe6060f1SDimitry Andric return true; 1663fe6060f1SDimitry Andric } 16645f757f3fSDimitry Andric std::swap(__temp, *__v); 1665fe6060f1SDimitry Andric *__v = *__p; 1666fe6060f1SDimitry Andric __m.unlock(); 1667fe6060f1SDimitry Andric return false; 1668fe6060f1SDimitry Andric } 1669fe6060f1SDimitry Andric 1670fe6060f1SDimitry Andric template <class _Tp> 1671cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool 1672cb14a3feSDimitry Andric atomic_compare_exchange_weak(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_ptr<_Tp> __w) { 1673bdd1243dSDimitry Andric return std::atomic_compare_exchange_strong(__p, __v, __w); 1674fe6060f1SDimitry Andric } 1675fe6060f1SDimitry Andric 1676fe6060f1SDimitry Andric template <class _Tp> 1677cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit( 1678cb14a3feSDimitry Andric shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_ptr<_Tp> __w, memory_order, memory_order) { 1679bdd1243dSDimitry Andric return std::atomic_compare_exchange_strong(__p, __v, __w); 1680fe6060f1SDimitry Andric } 1681fe6060f1SDimitry Andric 1682fe6060f1SDimitry Andric template <class _Tp> 1683cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit( 1684cb14a3feSDimitry Andric shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v, shared_ptr<_Tp> __w, memory_order, memory_order) { 1685bdd1243dSDimitry Andric return std::atomic_compare_exchange_weak(__p, __v, __w); 1686fe6060f1SDimitry Andric } 1687fe6060f1SDimitry Andric 1688349cc55cSDimitry Andric #endif // !defined(_LIBCPP_HAS_NO_THREADS) 1689fe6060f1SDimitry Andric 1690fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 1691fe6060f1SDimitry Andric 1692b3edf446SDimitry Andric _LIBCPP_POP_MACROS 1693b3edf446SDimitry Andric 1694fe6060f1SDimitry Andric #endif // _LIBCPP___MEMORY_SHARED_PTR_H 1695