138fd1498Szrj // shared_ptr and weak_ptr implementation details -*- C++ -*- 238fd1498Szrj 338fd1498Szrj // Copyright (C) 2007-2018 Free Software Foundation, Inc. 438fd1498Szrj // 538fd1498Szrj // This file is part of the GNU ISO C++ Library. This library is free 638fd1498Szrj // software; you can redistribute it and/or modify it under the 738fd1498Szrj // terms of the GNU General Public License as published by the 838fd1498Szrj // Free Software Foundation; either version 3, or (at your option) 938fd1498Szrj // any later version. 1038fd1498Szrj 1138fd1498Szrj // This library is distributed in the hope that it will be useful, 1238fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of 1338fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1438fd1498Szrj // GNU General Public License for more details. 1538fd1498Szrj 1638fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional 1738fd1498Szrj // permissions described in the GCC Runtime Library Exception, version 1838fd1498Szrj // 3.1, as published by the Free Software Foundation. 1938fd1498Szrj 2038fd1498Szrj // You should have received a copy of the GNU General Public License and 2138fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program; 2238fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 2338fd1498Szrj // <http://www.gnu.org/licenses/>. 2438fd1498Szrj 2538fd1498Szrj // GCC Note: Based on files from version 1.32.0 of the Boost library. 2638fd1498Szrj 2738fd1498Szrj // shared_count.hpp 2838fd1498Szrj // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. 2938fd1498Szrj 3038fd1498Szrj // shared_ptr.hpp 3138fd1498Szrj // Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes. 3238fd1498Szrj // Copyright (C) 2001, 2002, 2003 Peter Dimov 3338fd1498Szrj 3438fd1498Szrj // weak_ptr.hpp 3538fd1498Szrj // Copyright (C) 2001, 2002, 2003 Peter Dimov 3638fd1498Szrj 3738fd1498Szrj // enable_shared_from_this.hpp 3838fd1498Szrj // Copyright (C) 2002 Peter Dimov 3938fd1498Szrj 4038fd1498Szrj // Distributed under the Boost Software License, Version 1.0. (See 4138fd1498Szrj // accompanying file LICENSE_1_0.txt or copy at 4238fd1498Szrj // http://www.boost.org/LICENSE_1_0.txt) 4338fd1498Szrj 4438fd1498Szrj /** @file bits/shared_ptr_base.h 4538fd1498Szrj * This is an internal header file, included by other library headers. 4638fd1498Szrj * Do not attempt to use it directly. @headername{memory} 4738fd1498Szrj */ 4838fd1498Szrj 4938fd1498Szrj #ifndef _SHARED_PTR_BASE_H 5038fd1498Szrj #define _SHARED_PTR_BASE_H 1 5138fd1498Szrj 5238fd1498Szrj #include <typeinfo> 5338fd1498Szrj #include <bits/allocated_ptr.h> 5438fd1498Szrj #include <bits/refwrap.h> 5538fd1498Szrj #include <bits/stl_function.h> 5638fd1498Szrj #include <ext/aligned_buffer.h> 5738fd1498Szrj 5838fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default) 5938fd1498Szrj { 6038fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION 6138fd1498Szrj 6238fd1498Szrj #if _GLIBCXX_USE_DEPRECATED 6338fd1498Szrj #pragma GCC diagnostic push 6438fd1498Szrj #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 6538fd1498Szrj template<typename> class auto_ptr; 6638fd1498Szrj #pragma GCC diagnostic pop 6738fd1498Szrj #endif 6838fd1498Szrj 6938fd1498Szrj /** 7038fd1498Szrj * @brief Exception possibly thrown by @c shared_ptr. 7138fd1498Szrj * @ingroup exceptions 7238fd1498Szrj */ 7338fd1498Szrj class bad_weak_ptr : public std::exception 7438fd1498Szrj { 7538fd1498Szrj public: 7638fd1498Szrj virtual char const* what() const noexcept; 7738fd1498Szrj 7838fd1498Szrj virtual ~bad_weak_ptr() noexcept; 7938fd1498Szrj }; 8038fd1498Szrj 8138fd1498Szrj // Substitute for bad_weak_ptr object in the case of -fno-exceptions. 8238fd1498Szrj inline void 8338fd1498Szrj __throw_bad_weak_ptr() 8438fd1498Szrj { _GLIBCXX_THROW_OR_ABORT(bad_weak_ptr()); } 8538fd1498Szrj 8638fd1498Szrj using __gnu_cxx::_Lock_policy; 8738fd1498Szrj using __gnu_cxx::__default_lock_policy; 8838fd1498Szrj using __gnu_cxx::_S_single; 8938fd1498Szrj using __gnu_cxx::_S_mutex; 9038fd1498Szrj using __gnu_cxx::_S_atomic; 9138fd1498Szrj 9238fd1498Szrj // Empty helper class except when the template argument is _S_mutex. 9338fd1498Szrj template<_Lock_policy _Lp> 9438fd1498Szrj class _Mutex_base 9538fd1498Szrj { 9638fd1498Szrj protected: 9738fd1498Szrj // The atomic policy uses fully-fenced builtins, single doesn't care. 9838fd1498Szrj enum { _S_need_barriers = 0 }; 9938fd1498Szrj }; 10038fd1498Szrj 10138fd1498Szrj template<> 10238fd1498Szrj class _Mutex_base<_S_mutex> 10338fd1498Szrj : public __gnu_cxx::__mutex 10438fd1498Szrj { 10538fd1498Szrj protected: 10638fd1498Szrj // This policy is used when atomic builtins are not available. 10738fd1498Szrj // The replacement atomic operations might not have the necessary 10838fd1498Szrj // memory barriers. 10938fd1498Szrj enum { _S_need_barriers = 1 }; 11038fd1498Szrj }; 11138fd1498Szrj 11238fd1498Szrj template<_Lock_policy _Lp = __default_lock_policy> 11338fd1498Szrj class _Sp_counted_base 11438fd1498Szrj : public _Mutex_base<_Lp> 11538fd1498Szrj { 11638fd1498Szrj public: 11738fd1498Szrj _Sp_counted_base() noexcept 11838fd1498Szrj : _M_use_count(1), _M_weak_count(1) { } 11938fd1498Szrj 12038fd1498Szrj virtual 12138fd1498Szrj ~_Sp_counted_base() noexcept 12238fd1498Szrj { } 12338fd1498Szrj 12438fd1498Szrj // Called when _M_use_count drops to zero, to release the resources 12538fd1498Szrj // managed by *this. 12638fd1498Szrj virtual void 12738fd1498Szrj _M_dispose() noexcept = 0; 12838fd1498Szrj 12938fd1498Szrj // Called when _M_weak_count drops to zero. 13038fd1498Szrj virtual void 13138fd1498Szrj _M_destroy() noexcept 13238fd1498Szrj { delete this; } 13338fd1498Szrj 13438fd1498Szrj virtual void* 13538fd1498Szrj _M_get_deleter(const std::type_info&) noexcept = 0; 13638fd1498Szrj 13738fd1498Szrj void 13838fd1498Szrj _M_add_ref_copy() 13938fd1498Szrj { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); } 14038fd1498Szrj 14138fd1498Szrj void 14238fd1498Szrj _M_add_ref_lock(); 14338fd1498Szrj 14438fd1498Szrj bool 14538fd1498Szrj _M_add_ref_lock_nothrow(); 14638fd1498Szrj 14738fd1498Szrj void 14838fd1498Szrj _M_release() noexcept 14938fd1498Szrj { 15038fd1498Szrj // Be race-detector-friendly. For more info see bits/c++config. 15138fd1498Szrj _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count); 15238fd1498Szrj if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1) 15338fd1498Szrj { 15438fd1498Szrj _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count); 15538fd1498Szrj _M_dispose(); 15638fd1498Szrj // There must be a memory barrier between dispose() and destroy() 15738fd1498Szrj // to ensure that the effects of dispose() are observed in the 15838fd1498Szrj // thread that runs destroy(). 15938fd1498Szrj // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html 16038fd1498Szrj if (_Mutex_base<_Lp>::_S_need_barriers) 16138fd1498Szrj { 16238fd1498Szrj __atomic_thread_fence (__ATOMIC_ACQ_REL); 16338fd1498Szrj } 16438fd1498Szrj 16538fd1498Szrj // Be race-detector-friendly. For more info see bits/c++config. 16638fd1498Szrj _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count); 16738fd1498Szrj if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, 16838fd1498Szrj -1) == 1) 16938fd1498Szrj { 17038fd1498Szrj _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count); 17138fd1498Szrj _M_destroy(); 17238fd1498Szrj } 17338fd1498Szrj } 17438fd1498Szrj } 17538fd1498Szrj 17638fd1498Szrj void 17738fd1498Szrj _M_weak_add_ref() noexcept 17838fd1498Szrj { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); } 17938fd1498Szrj 18038fd1498Szrj void 18138fd1498Szrj _M_weak_release() noexcept 18238fd1498Szrj { 18338fd1498Szrj // Be race-detector-friendly. For more info see bits/c++config. 18438fd1498Szrj _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count); 18538fd1498Szrj if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1) 18638fd1498Szrj { 18738fd1498Szrj _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count); 18838fd1498Szrj if (_Mutex_base<_Lp>::_S_need_barriers) 18938fd1498Szrj { 19038fd1498Szrj // See _M_release(), 19138fd1498Szrj // destroy() must observe results of dispose() 19238fd1498Szrj __atomic_thread_fence (__ATOMIC_ACQ_REL); 19338fd1498Szrj } 19438fd1498Szrj _M_destroy(); 19538fd1498Szrj } 19638fd1498Szrj } 19738fd1498Szrj 19838fd1498Szrj long 19938fd1498Szrj _M_get_use_count() const noexcept 20038fd1498Szrj { 20138fd1498Szrj // No memory barrier is used here so there is no synchronization 20238fd1498Szrj // with other threads. 20338fd1498Szrj return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED); 20438fd1498Szrj } 20538fd1498Szrj 20638fd1498Szrj private: 20738fd1498Szrj _Sp_counted_base(_Sp_counted_base const&) = delete; 20838fd1498Szrj _Sp_counted_base& operator=(_Sp_counted_base const&) = delete; 20938fd1498Szrj 21038fd1498Szrj _Atomic_word _M_use_count; // #shared 21138fd1498Szrj _Atomic_word _M_weak_count; // #weak + (#shared != 0) 21238fd1498Szrj }; 21338fd1498Szrj 21438fd1498Szrj template<> 21538fd1498Szrj inline void 21638fd1498Szrj _Sp_counted_base<_S_single>:: 21738fd1498Szrj _M_add_ref_lock() 21838fd1498Szrj { 21938fd1498Szrj if (_M_use_count == 0) 22038fd1498Szrj __throw_bad_weak_ptr(); 22138fd1498Szrj ++_M_use_count; 22238fd1498Szrj } 22338fd1498Szrj 22438fd1498Szrj template<> 22538fd1498Szrj inline void 22638fd1498Szrj _Sp_counted_base<_S_mutex>:: 22738fd1498Szrj _M_add_ref_lock() 22838fd1498Szrj { 22938fd1498Szrj __gnu_cxx::__scoped_lock sentry(*this); 23038fd1498Szrj if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0) 23138fd1498Szrj { 23238fd1498Szrj _M_use_count = 0; 23338fd1498Szrj __throw_bad_weak_ptr(); 23438fd1498Szrj } 23538fd1498Szrj } 23638fd1498Szrj 23738fd1498Szrj template<> 23838fd1498Szrj inline void 23938fd1498Szrj _Sp_counted_base<_S_atomic>:: 24038fd1498Szrj _M_add_ref_lock() 24138fd1498Szrj { 24238fd1498Szrj // Perform lock-free add-if-not-zero operation. 24338fd1498Szrj _Atomic_word __count = _M_get_use_count(); 24438fd1498Szrj do 24538fd1498Szrj { 24638fd1498Szrj if (__count == 0) 24738fd1498Szrj __throw_bad_weak_ptr(); 24838fd1498Szrj // Replace the current counter value with the old value + 1, as 24938fd1498Szrj // long as it's not changed meanwhile. 25038fd1498Szrj } 25138fd1498Szrj while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1, 25238fd1498Szrj true, __ATOMIC_ACQ_REL, 25338fd1498Szrj __ATOMIC_RELAXED)); 25438fd1498Szrj } 25538fd1498Szrj 25638fd1498Szrj template<> 25738fd1498Szrj inline bool 25838fd1498Szrj _Sp_counted_base<_S_single>:: 25938fd1498Szrj _M_add_ref_lock_nothrow() 26038fd1498Szrj { 26138fd1498Szrj if (_M_use_count == 0) 26238fd1498Szrj return false; 26338fd1498Szrj ++_M_use_count; 26438fd1498Szrj return true; 26538fd1498Szrj } 26638fd1498Szrj 26738fd1498Szrj template<> 26838fd1498Szrj inline bool 26938fd1498Szrj _Sp_counted_base<_S_mutex>:: 27038fd1498Szrj _M_add_ref_lock_nothrow() 27138fd1498Szrj { 27238fd1498Szrj __gnu_cxx::__scoped_lock sentry(*this); 27338fd1498Szrj if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0) 27438fd1498Szrj { 27538fd1498Szrj _M_use_count = 0; 27638fd1498Szrj return false; 27738fd1498Szrj } 27838fd1498Szrj return true; 27938fd1498Szrj } 28038fd1498Szrj 28138fd1498Szrj template<> 28238fd1498Szrj inline bool 28338fd1498Szrj _Sp_counted_base<_S_atomic>:: 28438fd1498Szrj _M_add_ref_lock_nothrow() 28538fd1498Szrj { 28638fd1498Szrj // Perform lock-free add-if-not-zero operation. 28738fd1498Szrj _Atomic_word __count = _M_get_use_count(); 28838fd1498Szrj do 28938fd1498Szrj { 29038fd1498Szrj if (__count == 0) 29138fd1498Szrj return false; 29238fd1498Szrj // Replace the current counter value with the old value + 1, as 29338fd1498Szrj // long as it's not changed meanwhile. 29438fd1498Szrj } 29538fd1498Szrj while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1, 29638fd1498Szrj true, __ATOMIC_ACQ_REL, 29738fd1498Szrj __ATOMIC_RELAXED)); 29838fd1498Szrj return true; 29938fd1498Szrj } 30038fd1498Szrj 30138fd1498Szrj template<> 30238fd1498Szrj inline void 30338fd1498Szrj _Sp_counted_base<_S_single>::_M_add_ref_copy() 30438fd1498Szrj { ++_M_use_count; } 30538fd1498Szrj 30638fd1498Szrj template<> 30738fd1498Szrj inline void 30838fd1498Szrj _Sp_counted_base<_S_single>::_M_release() noexcept 30938fd1498Szrj { 31038fd1498Szrj if (--_M_use_count == 0) 31138fd1498Szrj { 31238fd1498Szrj _M_dispose(); 31338fd1498Szrj if (--_M_weak_count == 0) 31438fd1498Szrj _M_destroy(); 31538fd1498Szrj } 31638fd1498Szrj } 31738fd1498Szrj 31838fd1498Szrj template<> 31938fd1498Szrj inline void 32038fd1498Szrj _Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept 32138fd1498Szrj { ++_M_weak_count; } 32238fd1498Szrj 32338fd1498Szrj template<> 32438fd1498Szrj inline void 32538fd1498Szrj _Sp_counted_base<_S_single>::_M_weak_release() noexcept 32638fd1498Szrj { 32738fd1498Szrj if (--_M_weak_count == 0) 32838fd1498Szrj _M_destroy(); 32938fd1498Szrj } 33038fd1498Szrj 33138fd1498Szrj template<> 33238fd1498Szrj inline long 33338fd1498Szrj _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept 33438fd1498Szrj { return _M_use_count; } 33538fd1498Szrj 33638fd1498Szrj 33738fd1498Szrj // Forward declarations. 33838fd1498Szrj template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> 33938fd1498Szrj class __shared_ptr; 34038fd1498Szrj 34138fd1498Szrj template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> 34238fd1498Szrj class __weak_ptr; 34338fd1498Szrj 34438fd1498Szrj template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> 34538fd1498Szrj class __enable_shared_from_this; 34638fd1498Szrj 34738fd1498Szrj template<typename _Tp> 34838fd1498Szrj class shared_ptr; 34938fd1498Szrj 35038fd1498Szrj template<typename _Tp> 35138fd1498Szrj class weak_ptr; 35238fd1498Szrj 35338fd1498Szrj template<typename _Tp> 35438fd1498Szrj struct owner_less; 35538fd1498Szrj 35638fd1498Szrj template<typename _Tp> 35738fd1498Szrj class enable_shared_from_this; 35838fd1498Szrj 35938fd1498Szrj template<_Lock_policy _Lp = __default_lock_policy> 36038fd1498Szrj class __weak_count; 36138fd1498Szrj 36238fd1498Szrj template<_Lock_policy _Lp = __default_lock_policy> 36338fd1498Szrj class __shared_count; 36438fd1498Szrj 36538fd1498Szrj 36638fd1498Szrj // Counted ptr with no deleter or allocator support 36738fd1498Szrj template<typename _Ptr, _Lock_policy _Lp> 36838fd1498Szrj class _Sp_counted_ptr final : public _Sp_counted_base<_Lp> 36938fd1498Szrj { 37038fd1498Szrj public: 37138fd1498Szrj explicit 37238fd1498Szrj _Sp_counted_ptr(_Ptr __p) noexcept 37338fd1498Szrj : _M_ptr(__p) { } 37438fd1498Szrj 37538fd1498Szrj virtual void 37638fd1498Szrj _M_dispose() noexcept 37738fd1498Szrj { delete _M_ptr; } 37838fd1498Szrj 37938fd1498Szrj virtual void 38038fd1498Szrj _M_destroy() noexcept 38138fd1498Szrj { delete this; } 38238fd1498Szrj 38338fd1498Szrj virtual void* 38438fd1498Szrj _M_get_deleter(const std::type_info&) noexcept 38538fd1498Szrj { return nullptr; } 38638fd1498Szrj 38738fd1498Szrj _Sp_counted_ptr(const _Sp_counted_ptr&) = delete; 38838fd1498Szrj _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete; 38938fd1498Szrj 39038fd1498Szrj private: 39138fd1498Szrj _Ptr _M_ptr; 39238fd1498Szrj }; 39338fd1498Szrj 39438fd1498Szrj template<> 39538fd1498Szrj inline void 39638fd1498Szrj _Sp_counted_ptr<nullptr_t, _S_single>::_M_dispose() noexcept { } 39738fd1498Szrj 39838fd1498Szrj template<> 39938fd1498Szrj inline void 40038fd1498Szrj _Sp_counted_ptr<nullptr_t, _S_mutex>::_M_dispose() noexcept { } 40138fd1498Szrj 40238fd1498Szrj template<> 40338fd1498Szrj inline void 40438fd1498Szrj _Sp_counted_ptr<nullptr_t, _S_atomic>::_M_dispose() noexcept { } 40538fd1498Szrj 40638fd1498Szrj template<int _Nm, typename _Tp, 40738fd1498Szrj bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)> 40838fd1498Szrj struct _Sp_ebo_helper; 40938fd1498Szrj 41038fd1498Szrj /// Specialization using EBO. 41138fd1498Szrj template<int _Nm, typename _Tp> 41238fd1498Szrj struct _Sp_ebo_helper<_Nm, _Tp, true> : private _Tp 41338fd1498Szrj { 41438fd1498Szrj explicit _Sp_ebo_helper(const _Tp& __tp) : _Tp(__tp) { } 41538fd1498Szrj explicit _Sp_ebo_helper(_Tp&& __tp) : _Tp(std::move(__tp)) { } 41638fd1498Szrj 41738fd1498Szrj static _Tp& 41838fd1498Szrj _S_get(_Sp_ebo_helper& __eboh) { return static_cast<_Tp&>(__eboh); } 41938fd1498Szrj }; 42038fd1498Szrj 42138fd1498Szrj /// Specialization not using EBO. 42238fd1498Szrj template<int _Nm, typename _Tp> 42338fd1498Szrj struct _Sp_ebo_helper<_Nm, _Tp, false> 42438fd1498Szrj { 42538fd1498Szrj explicit _Sp_ebo_helper(const _Tp& __tp) : _M_tp(__tp) { } 42638fd1498Szrj explicit _Sp_ebo_helper(_Tp&& __tp) : _M_tp(std::move(__tp)) { } 42738fd1498Szrj 42838fd1498Szrj static _Tp& 42938fd1498Szrj _S_get(_Sp_ebo_helper& __eboh) 43038fd1498Szrj { return __eboh._M_tp; } 43138fd1498Szrj 43238fd1498Szrj private: 43338fd1498Szrj _Tp _M_tp; 43438fd1498Szrj }; 43538fd1498Szrj 43638fd1498Szrj // Support for custom deleter and/or allocator 43738fd1498Szrj template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp> 43838fd1498Szrj class _Sp_counted_deleter final : public _Sp_counted_base<_Lp> 43938fd1498Szrj { 44038fd1498Szrj class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc> 44138fd1498Szrj { 44238fd1498Szrj typedef _Sp_ebo_helper<0, _Deleter> _Del_base; 44338fd1498Szrj typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base; 44438fd1498Szrj 44538fd1498Szrj public: 44638fd1498Szrj _Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept 44738fd1498Szrj : _M_ptr(__p), _Del_base(std::move(__d)), _Alloc_base(__a) 44838fd1498Szrj { } 44938fd1498Szrj 45038fd1498Szrj _Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); } 45138fd1498Szrj _Alloc& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); } 45238fd1498Szrj 45338fd1498Szrj _Ptr _M_ptr; 45438fd1498Szrj }; 45538fd1498Szrj 45638fd1498Szrj public: 45738fd1498Szrj using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_deleter>; 45838fd1498Szrj 45938fd1498Szrj // __d(__p) must not throw. 46038fd1498Szrj _Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept 46138fd1498Szrj : _M_impl(__p, std::move(__d), _Alloc()) { } 46238fd1498Szrj 46338fd1498Szrj // __d(__p) must not throw. 46438fd1498Szrj _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept 46538fd1498Szrj : _M_impl(__p, std::move(__d), __a) { } 46638fd1498Szrj 46738fd1498Szrj ~_Sp_counted_deleter() noexcept { } 46838fd1498Szrj 46938fd1498Szrj virtual void 47038fd1498Szrj _M_dispose() noexcept 47138fd1498Szrj { _M_impl._M_del()(_M_impl._M_ptr); } 47238fd1498Szrj 47338fd1498Szrj virtual void 47438fd1498Szrj _M_destroy() noexcept 47538fd1498Szrj { 47638fd1498Szrj __allocator_type __a(_M_impl._M_alloc()); 47738fd1498Szrj __allocated_ptr<__allocator_type> __guard_ptr{ __a, this }; 47838fd1498Szrj this->~_Sp_counted_deleter(); 47938fd1498Szrj } 48038fd1498Szrj 48138fd1498Szrj virtual void* 48238fd1498Szrj _M_get_deleter(const std::type_info& __ti) noexcept 48338fd1498Szrj { 48438fd1498Szrj #if __cpp_rtti 48538fd1498Szrj // _GLIBCXX_RESOLVE_LIB_DEFECTS 48638fd1498Szrj // 2400. shared_ptr's get_deleter() should use addressof() 48738fd1498Szrj return __ti == typeid(_Deleter) 48838fd1498Szrj ? std::__addressof(_M_impl._M_del()) 48938fd1498Szrj : nullptr; 49038fd1498Szrj #else 49138fd1498Szrj return nullptr; 49238fd1498Szrj #endif 49338fd1498Szrj } 49438fd1498Szrj 49538fd1498Szrj private: 49638fd1498Szrj _Impl _M_impl; 49738fd1498Szrj }; 49838fd1498Szrj 49938fd1498Szrj // helpers for make_shared / allocate_shared 50038fd1498Szrj 50138fd1498Szrj struct _Sp_make_shared_tag 50238fd1498Szrj { 50338fd1498Szrj private: 50438fd1498Szrj template<typename _Tp, typename _Alloc, _Lock_policy _Lp> 50538fd1498Szrj friend class _Sp_counted_ptr_inplace; 50638fd1498Szrj 50738fd1498Szrj static const type_info& 508*58e805e6Szrj _S_ti() noexcept _GLIBCXX_VISIBILITY(default) 50938fd1498Szrj { 510*58e805e6Szrj alignas(type_info) static constexpr char __tag[sizeof(type_info)] = { }; 51138fd1498Szrj return reinterpret_cast<const type_info&>(__tag); 51238fd1498Szrj } 513*58e805e6Szrj }; 514*58e805e6Szrj 515*58e805e6Szrj template<typename _Alloc> 516*58e805e6Szrj struct _Sp_alloc_shared_tag 517*58e805e6Szrj { 518*58e805e6Szrj const _Alloc& _M_a; 51938fd1498Szrj }; 52038fd1498Szrj 52138fd1498Szrj template<typename _Tp, typename _Alloc, _Lock_policy _Lp> 52238fd1498Szrj class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp> 52338fd1498Szrj { 52438fd1498Szrj class _Impl : _Sp_ebo_helper<0, _Alloc> 52538fd1498Szrj { 52638fd1498Szrj typedef _Sp_ebo_helper<0, _Alloc> _A_base; 52738fd1498Szrj 52838fd1498Szrj public: 52938fd1498Szrj explicit _Impl(_Alloc __a) noexcept : _A_base(__a) { } 53038fd1498Szrj 53138fd1498Szrj _Alloc& _M_alloc() noexcept { return _A_base::_S_get(*this); } 53238fd1498Szrj 53338fd1498Szrj __gnu_cxx::__aligned_buffer<_Tp> _M_storage; 53438fd1498Szrj }; 53538fd1498Szrj 53638fd1498Szrj public: 53738fd1498Szrj using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>; 53838fd1498Szrj 53938fd1498Szrj template<typename... _Args> 54038fd1498Szrj _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args) 54138fd1498Szrj : _M_impl(__a) 54238fd1498Szrj { 54338fd1498Szrj // _GLIBCXX_RESOLVE_LIB_DEFECTS 54438fd1498Szrj // 2070. allocate_shared should use allocator_traits<A>::construct 54538fd1498Szrj allocator_traits<_Alloc>::construct(__a, _M_ptr(), 54638fd1498Szrj std::forward<_Args>(__args)...); // might throw 54738fd1498Szrj } 54838fd1498Szrj 54938fd1498Szrj ~_Sp_counted_ptr_inplace() noexcept { } 55038fd1498Szrj 55138fd1498Szrj virtual void 55238fd1498Szrj _M_dispose() noexcept 55338fd1498Szrj { 55438fd1498Szrj allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr()); 55538fd1498Szrj } 55638fd1498Szrj 55738fd1498Szrj // Override because the allocator needs to know the dynamic type 55838fd1498Szrj virtual void 55938fd1498Szrj _M_destroy() noexcept 56038fd1498Szrj { 56138fd1498Szrj __allocator_type __a(_M_impl._M_alloc()); 56238fd1498Szrj __allocated_ptr<__allocator_type> __guard_ptr{ __a, this }; 56338fd1498Szrj this->~_Sp_counted_ptr_inplace(); 56438fd1498Szrj } 56538fd1498Szrj 566*58e805e6Szrj private: 567*58e805e6Szrj friend class __shared_count<_Lp>; // To be able to call _M_ptr(). 568*58e805e6Szrj 569*58e805e6Szrj // No longer used, but code compiled against old libstdc++ headers 570*58e805e6Szrj // might still call it from __shared_ptr ctor to get the pointer out. 57138fd1498Szrj virtual void* 572*58e805e6Szrj _M_get_deleter(const std::type_info& __ti) noexcept override 57338fd1498Szrj { 574*58e805e6Szrj // Check for the fake type_info first, so we don't try to access it 575*58e805e6Szrj // as a real type_info object. 57638fd1498Szrj if (&__ti == &_Sp_make_shared_tag::_S_ti()) 57738fd1498Szrj return const_cast<typename remove_cv<_Tp>::type*>(_M_ptr()); 578*58e805e6Szrj #if __cpp_rtti 579*58e805e6Szrj // Callers compiled with old libstdc++ headers and RTTI enabled 580*58e805e6Szrj // might pass this instead: 581*58e805e6Szrj else if (__ti == typeid(_Sp_make_shared_tag)) 582*58e805e6Szrj return const_cast<typename remove_cv<_Tp>::type*>(_M_ptr()); 583*58e805e6Szrj #else 584*58e805e6Szrj // Cannot detect a real type_info object. If the linker keeps a 585*58e805e6Szrj // definition of this function compiled with -fno-rtti then callers 586*58e805e6Szrj // that have RTTI enabled and pass a real type_info object will get 587*58e805e6Szrj // a null pointer returned. 588*58e805e6Szrj #endif 58938fd1498Szrj return nullptr; 59038fd1498Szrj } 59138fd1498Szrj 59238fd1498Szrj _Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); } 59338fd1498Szrj 59438fd1498Szrj _Impl _M_impl; 59538fd1498Szrj }; 59638fd1498Szrj 59738fd1498Szrj // The default deleter for shared_ptr<T[]> and shared_ptr<T[N]>. 59838fd1498Szrj struct __sp_array_delete 59938fd1498Szrj { 60038fd1498Szrj template<typename _Yp> 60138fd1498Szrj void operator()(_Yp* __p) const { delete[] __p; } 60238fd1498Szrj }; 60338fd1498Szrj 60438fd1498Szrj template<_Lock_policy _Lp> 60538fd1498Szrj class __shared_count 60638fd1498Szrj { 607*58e805e6Szrj template<typename _Tp> 608*58e805e6Szrj struct __not_alloc_shared_tag { using type = void; }; 609*58e805e6Szrj 610*58e805e6Szrj template<typename _Tp> 611*58e805e6Szrj struct __not_alloc_shared_tag<_Sp_alloc_shared_tag<_Tp>> { }; 612*58e805e6Szrj 61338fd1498Szrj public: 61438fd1498Szrj constexpr __shared_count() noexcept : _M_pi(0) 61538fd1498Szrj { } 61638fd1498Szrj 61738fd1498Szrj template<typename _Ptr> 61838fd1498Szrj explicit 61938fd1498Szrj __shared_count(_Ptr __p) : _M_pi(0) 62038fd1498Szrj { 62138fd1498Szrj __try 62238fd1498Szrj { 62338fd1498Szrj _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p); 62438fd1498Szrj } 62538fd1498Szrj __catch(...) 62638fd1498Szrj { 62738fd1498Szrj delete __p; 62838fd1498Szrj __throw_exception_again; 62938fd1498Szrj } 63038fd1498Szrj } 63138fd1498Szrj 63238fd1498Szrj template<typename _Ptr> 63338fd1498Szrj __shared_count(_Ptr __p, /* is_array = */ false_type) 63438fd1498Szrj : __shared_count(__p) 63538fd1498Szrj { } 63638fd1498Szrj 63738fd1498Szrj template<typename _Ptr> 63838fd1498Szrj __shared_count(_Ptr __p, /* is_array = */ true_type) 63938fd1498Szrj : __shared_count(__p, __sp_array_delete{}, allocator<void>()) 64038fd1498Szrj { } 64138fd1498Szrj 642*58e805e6Szrj template<typename _Ptr, typename _Deleter, 643*58e805e6Szrj typename = typename __not_alloc_shared_tag<_Deleter>::type> 64438fd1498Szrj __shared_count(_Ptr __p, _Deleter __d) 64538fd1498Szrj : __shared_count(__p, std::move(__d), allocator<void>()) 64638fd1498Szrj { } 64738fd1498Szrj 648*58e805e6Szrj template<typename _Ptr, typename _Deleter, typename _Alloc, 649*58e805e6Szrj typename = typename __not_alloc_shared_tag<_Deleter>::type> 65038fd1498Szrj __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0) 65138fd1498Szrj { 65238fd1498Szrj typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type; 65338fd1498Szrj __try 65438fd1498Szrj { 65538fd1498Szrj typename _Sp_cd_type::__allocator_type __a2(__a); 65638fd1498Szrj auto __guard = std::__allocate_guarded(__a2); 65738fd1498Szrj _Sp_cd_type* __mem = __guard.get(); 65838fd1498Szrj ::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a)); 65938fd1498Szrj _M_pi = __mem; 66038fd1498Szrj __guard = nullptr; 66138fd1498Szrj } 66238fd1498Szrj __catch(...) 66338fd1498Szrj { 66438fd1498Szrj __d(__p); // Call _Deleter on __p. 66538fd1498Szrj __throw_exception_again; 66638fd1498Szrj } 66738fd1498Szrj } 66838fd1498Szrj 66938fd1498Szrj template<typename _Tp, typename _Alloc, typename... _Args> 670*58e805e6Szrj __shared_count(_Tp*& __p, _Sp_alloc_shared_tag<_Alloc> __a, 67138fd1498Szrj _Args&&... __args) 67238fd1498Szrj { 67338fd1498Szrj typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type; 674*58e805e6Szrj typename _Sp_cp_type::__allocator_type __a2(__a._M_a); 67538fd1498Szrj auto __guard = std::__allocate_guarded(__a2); 67638fd1498Szrj _Sp_cp_type* __mem = __guard.get(); 677*58e805e6Szrj auto __pi = ::new (__mem) 678*58e805e6Szrj _Sp_cp_type(__a._M_a, std::forward<_Args>(__args)...); 67938fd1498Szrj __guard = nullptr; 680*58e805e6Szrj _M_pi = __pi; 681*58e805e6Szrj __p = __pi->_M_ptr(); 68238fd1498Szrj } 68338fd1498Szrj 68438fd1498Szrj #if _GLIBCXX_USE_DEPRECATED 68538fd1498Szrj #pragma GCC diagnostic push 68638fd1498Szrj #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 68738fd1498Szrj // Special case for auto_ptr<_Tp> to provide the strong guarantee. 68838fd1498Szrj template<typename _Tp> 68938fd1498Szrj explicit 69038fd1498Szrj __shared_count(std::auto_ptr<_Tp>&& __r); 69138fd1498Szrj #pragma GCC diagnostic pop 69238fd1498Szrj #endif 69338fd1498Szrj 69438fd1498Szrj // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee. 69538fd1498Szrj template<typename _Tp, typename _Del> 69638fd1498Szrj explicit 69738fd1498Szrj __shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0) 69838fd1498Szrj { 69938fd1498Szrj // _GLIBCXX_RESOLVE_LIB_DEFECTS 70038fd1498Szrj // 2415. Inconsistency between unique_ptr and shared_ptr 70138fd1498Szrj if (__r.get() == nullptr) 70238fd1498Szrj return; 70338fd1498Szrj 70438fd1498Szrj using _Ptr = typename unique_ptr<_Tp, _Del>::pointer; 70538fd1498Szrj using _Del2 = typename conditional<is_reference<_Del>::value, 70638fd1498Szrj reference_wrapper<typename remove_reference<_Del>::type>, 70738fd1498Szrj _Del>::type; 70838fd1498Szrj using _Sp_cd_type 70938fd1498Szrj = _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>; 71038fd1498Szrj using _Alloc = allocator<_Sp_cd_type>; 71138fd1498Szrj using _Alloc_traits = allocator_traits<_Alloc>; 71238fd1498Szrj _Alloc __a; 71338fd1498Szrj _Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1); 71438fd1498Szrj _Alloc_traits::construct(__a, __mem, __r.release(), 71538fd1498Szrj __r.get_deleter()); // non-throwing 71638fd1498Szrj _M_pi = __mem; 71738fd1498Szrj } 71838fd1498Szrj 71938fd1498Szrj // Throw bad_weak_ptr when __r._M_get_use_count() == 0. 72038fd1498Szrj explicit __shared_count(const __weak_count<_Lp>& __r); 72138fd1498Szrj 72238fd1498Szrj // Does not throw if __r._M_get_use_count() == 0, caller must check. 72338fd1498Szrj explicit __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t); 72438fd1498Szrj 72538fd1498Szrj ~__shared_count() noexcept 72638fd1498Szrj { 72738fd1498Szrj if (_M_pi != nullptr) 72838fd1498Szrj _M_pi->_M_release(); 72938fd1498Szrj } 73038fd1498Szrj 73138fd1498Szrj __shared_count(const __shared_count& __r) noexcept 73238fd1498Szrj : _M_pi(__r._M_pi) 73338fd1498Szrj { 73438fd1498Szrj if (_M_pi != 0) 73538fd1498Szrj _M_pi->_M_add_ref_copy(); 73638fd1498Szrj } 73738fd1498Szrj 73838fd1498Szrj __shared_count& 73938fd1498Szrj operator=(const __shared_count& __r) noexcept 74038fd1498Szrj { 74138fd1498Szrj _Sp_counted_base<_Lp>* __tmp = __r._M_pi; 74238fd1498Szrj if (__tmp != _M_pi) 74338fd1498Szrj { 74438fd1498Szrj if (__tmp != 0) 74538fd1498Szrj __tmp->_M_add_ref_copy(); 74638fd1498Szrj if (_M_pi != 0) 74738fd1498Szrj _M_pi->_M_release(); 74838fd1498Szrj _M_pi = __tmp; 74938fd1498Szrj } 75038fd1498Szrj return *this; 75138fd1498Szrj } 75238fd1498Szrj 75338fd1498Szrj void 75438fd1498Szrj _M_swap(__shared_count& __r) noexcept 75538fd1498Szrj { 75638fd1498Szrj _Sp_counted_base<_Lp>* __tmp = __r._M_pi; 75738fd1498Szrj __r._M_pi = _M_pi; 75838fd1498Szrj _M_pi = __tmp; 75938fd1498Szrj } 76038fd1498Szrj 76138fd1498Szrj long 76238fd1498Szrj _M_get_use_count() const noexcept 76338fd1498Szrj { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; } 76438fd1498Szrj 76538fd1498Szrj bool 76638fd1498Szrj _M_unique() const noexcept 76738fd1498Szrj { return this->_M_get_use_count() == 1; } 76838fd1498Szrj 76938fd1498Szrj void* 77038fd1498Szrj _M_get_deleter(const std::type_info& __ti) const noexcept 77138fd1498Szrj { return _M_pi ? _M_pi->_M_get_deleter(__ti) : nullptr; } 77238fd1498Szrj 77338fd1498Szrj bool 77438fd1498Szrj _M_less(const __shared_count& __rhs) const noexcept 77538fd1498Szrj { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } 77638fd1498Szrj 77738fd1498Szrj bool 77838fd1498Szrj _M_less(const __weak_count<_Lp>& __rhs) const noexcept 77938fd1498Szrj { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } 78038fd1498Szrj 78138fd1498Szrj // Friend function injected into enclosing namespace and found by ADL 78238fd1498Szrj friend inline bool 78338fd1498Szrj operator==(const __shared_count& __a, const __shared_count& __b) noexcept 78438fd1498Szrj { return __a._M_pi == __b._M_pi; } 78538fd1498Szrj 78638fd1498Szrj private: 78738fd1498Szrj friend class __weak_count<_Lp>; 78838fd1498Szrj 78938fd1498Szrj _Sp_counted_base<_Lp>* _M_pi; 79038fd1498Szrj }; 79138fd1498Szrj 79238fd1498Szrj 79338fd1498Szrj template<_Lock_policy _Lp> 79438fd1498Szrj class __weak_count 79538fd1498Szrj { 79638fd1498Szrj public: 79738fd1498Szrj constexpr __weak_count() noexcept : _M_pi(nullptr) 79838fd1498Szrj { } 79938fd1498Szrj 80038fd1498Szrj __weak_count(const __shared_count<_Lp>& __r) noexcept 80138fd1498Szrj : _M_pi(__r._M_pi) 80238fd1498Szrj { 80338fd1498Szrj if (_M_pi != nullptr) 80438fd1498Szrj _M_pi->_M_weak_add_ref(); 80538fd1498Szrj } 80638fd1498Szrj 80738fd1498Szrj __weak_count(const __weak_count& __r) noexcept 80838fd1498Szrj : _M_pi(__r._M_pi) 80938fd1498Szrj { 81038fd1498Szrj if (_M_pi != nullptr) 81138fd1498Szrj _M_pi->_M_weak_add_ref(); 81238fd1498Szrj } 81338fd1498Szrj 81438fd1498Szrj __weak_count(__weak_count&& __r) noexcept 81538fd1498Szrj : _M_pi(__r._M_pi) 81638fd1498Szrj { __r._M_pi = nullptr; } 81738fd1498Szrj 81838fd1498Szrj ~__weak_count() noexcept 81938fd1498Szrj { 82038fd1498Szrj if (_M_pi != nullptr) 82138fd1498Szrj _M_pi->_M_weak_release(); 82238fd1498Szrj } 82338fd1498Szrj 82438fd1498Szrj __weak_count& 82538fd1498Szrj operator=(const __shared_count<_Lp>& __r) noexcept 82638fd1498Szrj { 82738fd1498Szrj _Sp_counted_base<_Lp>* __tmp = __r._M_pi; 82838fd1498Szrj if (__tmp != nullptr) 82938fd1498Szrj __tmp->_M_weak_add_ref(); 83038fd1498Szrj if (_M_pi != nullptr) 83138fd1498Szrj _M_pi->_M_weak_release(); 83238fd1498Szrj _M_pi = __tmp; 83338fd1498Szrj return *this; 83438fd1498Szrj } 83538fd1498Szrj 83638fd1498Szrj __weak_count& 83738fd1498Szrj operator=(const __weak_count& __r) noexcept 83838fd1498Szrj { 83938fd1498Szrj _Sp_counted_base<_Lp>* __tmp = __r._M_pi; 84038fd1498Szrj if (__tmp != nullptr) 84138fd1498Szrj __tmp->_M_weak_add_ref(); 84238fd1498Szrj if (_M_pi != nullptr) 84338fd1498Szrj _M_pi->_M_weak_release(); 84438fd1498Szrj _M_pi = __tmp; 84538fd1498Szrj return *this; 84638fd1498Szrj } 84738fd1498Szrj 84838fd1498Szrj __weak_count& 84938fd1498Szrj operator=(__weak_count&& __r) noexcept 85038fd1498Szrj { 85138fd1498Szrj if (_M_pi != nullptr) 85238fd1498Szrj _M_pi->_M_weak_release(); 85338fd1498Szrj _M_pi = __r._M_pi; 85438fd1498Szrj __r._M_pi = nullptr; 85538fd1498Szrj return *this; 85638fd1498Szrj } 85738fd1498Szrj 85838fd1498Szrj void 85938fd1498Szrj _M_swap(__weak_count& __r) noexcept 86038fd1498Szrj { 86138fd1498Szrj _Sp_counted_base<_Lp>* __tmp = __r._M_pi; 86238fd1498Szrj __r._M_pi = _M_pi; 86338fd1498Szrj _M_pi = __tmp; 86438fd1498Szrj } 86538fd1498Szrj 86638fd1498Szrj long 86738fd1498Szrj _M_get_use_count() const noexcept 86838fd1498Szrj { return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; } 86938fd1498Szrj 87038fd1498Szrj bool 87138fd1498Szrj _M_less(const __weak_count& __rhs) const noexcept 87238fd1498Szrj { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } 87338fd1498Szrj 87438fd1498Szrj bool 87538fd1498Szrj _M_less(const __shared_count<_Lp>& __rhs) const noexcept 87638fd1498Szrj { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } 87738fd1498Szrj 87838fd1498Szrj // Friend function injected into enclosing namespace and found by ADL 87938fd1498Szrj friend inline bool 88038fd1498Szrj operator==(const __weak_count& __a, const __weak_count& __b) noexcept 88138fd1498Szrj { return __a._M_pi == __b._M_pi; } 88238fd1498Szrj 88338fd1498Szrj private: 88438fd1498Szrj friend class __shared_count<_Lp>; 88538fd1498Szrj 88638fd1498Szrj _Sp_counted_base<_Lp>* _M_pi; 88738fd1498Szrj }; 88838fd1498Szrj 88938fd1498Szrj // Now that __weak_count is defined we can define this constructor: 89038fd1498Szrj template<_Lock_policy _Lp> 89138fd1498Szrj inline 89238fd1498Szrj __shared_count<_Lp>::__shared_count(const __weak_count<_Lp>& __r) 89338fd1498Szrj : _M_pi(__r._M_pi) 89438fd1498Szrj { 89538fd1498Szrj if (_M_pi != nullptr) 89638fd1498Szrj _M_pi->_M_add_ref_lock(); 89738fd1498Szrj else 89838fd1498Szrj __throw_bad_weak_ptr(); 89938fd1498Szrj } 90038fd1498Szrj 90138fd1498Szrj // Now that __weak_count is defined we can define this constructor: 90238fd1498Szrj template<_Lock_policy _Lp> 90338fd1498Szrj inline 90438fd1498Szrj __shared_count<_Lp>:: 90538fd1498Szrj __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t) 90638fd1498Szrj : _M_pi(__r._M_pi) 90738fd1498Szrj { 90838fd1498Szrj if (_M_pi != nullptr) 90938fd1498Szrj if (!_M_pi->_M_add_ref_lock_nothrow()) 91038fd1498Szrj _M_pi = nullptr; 91138fd1498Szrj } 91238fd1498Szrj 91338fd1498Szrj #define __cpp_lib_shared_ptr_arrays 201603 91438fd1498Szrj 91538fd1498Szrj // Helper traits for shared_ptr of array: 91638fd1498Szrj 91738fd1498Szrj // A pointer type Y* is said to be compatible with a pointer type T* when 91838fd1498Szrj // either Y* is convertible to T* or Y is U[N] and T is U cv []. 91938fd1498Szrj template<typename _Yp_ptr, typename _Tp_ptr> 92038fd1498Szrj struct __sp_compatible_with 92138fd1498Szrj : false_type 92238fd1498Szrj { }; 92338fd1498Szrj 92438fd1498Szrj template<typename _Yp, typename _Tp> 92538fd1498Szrj struct __sp_compatible_with<_Yp*, _Tp*> 92638fd1498Szrj : is_convertible<_Yp*, _Tp*>::type 92738fd1498Szrj { }; 92838fd1498Szrj 92938fd1498Szrj template<typename _Up, size_t _Nm> 93038fd1498Szrj struct __sp_compatible_with<_Up(*)[_Nm], _Up(*)[]> 93138fd1498Szrj : true_type 93238fd1498Szrj { }; 93338fd1498Szrj 93438fd1498Szrj template<typename _Up, size_t _Nm> 93538fd1498Szrj struct __sp_compatible_with<_Up(*)[_Nm], const _Up(*)[]> 93638fd1498Szrj : true_type 93738fd1498Szrj { }; 93838fd1498Szrj 93938fd1498Szrj template<typename _Up, size_t _Nm> 94038fd1498Szrj struct __sp_compatible_with<_Up(*)[_Nm], volatile _Up(*)[]> 94138fd1498Szrj : true_type 94238fd1498Szrj { }; 94338fd1498Szrj 94438fd1498Szrj template<typename _Up, size_t _Nm> 94538fd1498Szrj struct __sp_compatible_with<_Up(*)[_Nm], const volatile _Up(*)[]> 94638fd1498Szrj : true_type 94738fd1498Szrj { }; 94838fd1498Szrj 94938fd1498Szrj // Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N]. 95038fd1498Szrj template<typename _Up, size_t _Nm, typename _Yp, typename = void> 95138fd1498Szrj struct __sp_is_constructible_arrN 95238fd1498Szrj : false_type 95338fd1498Szrj { }; 95438fd1498Szrj 95538fd1498Szrj template<typename _Up, size_t _Nm, typename _Yp> 95638fd1498Szrj struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>> 95738fd1498Szrj : is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type 95838fd1498Szrj { }; 95938fd1498Szrj 96038fd1498Szrj // Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[]. 96138fd1498Szrj template<typename _Up, typename _Yp, typename = void> 96238fd1498Szrj struct __sp_is_constructible_arr 96338fd1498Szrj : false_type 96438fd1498Szrj { }; 96538fd1498Szrj 96638fd1498Szrj template<typename _Up, typename _Yp> 96738fd1498Szrj struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>> 96838fd1498Szrj : is_convertible<_Yp(*)[], _Up(*)[]>::type 96938fd1498Szrj { }; 97038fd1498Szrj 97138fd1498Szrj // Trait to check if shared_ptr<T> can be constructed from Y*. 97238fd1498Szrj template<typename _Tp, typename _Yp> 97338fd1498Szrj struct __sp_is_constructible; 97438fd1498Szrj 97538fd1498Szrj // When T is U[N], Y(*)[N] shall be convertible to T*; 97638fd1498Szrj template<typename _Up, size_t _Nm, typename _Yp> 97738fd1498Szrj struct __sp_is_constructible<_Up[_Nm], _Yp> 97838fd1498Szrj : __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type 97938fd1498Szrj { }; 98038fd1498Szrj 98138fd1498Szrj // when T is U[], Y(*)[] shall be convertible to T*; 98238fd1498Szrj template<typename _Up, typename _Yp> 98338fd1498Szrj struct __sp_is_constructible<_Up[], _Yp> 98438fd1498Szrj : __sp_is_constructible_arr<_Up, _Yp>::type 98538fd1498Szrj { }; 98638fd1498Szrj 98738fd1498Szrj // otherwise, Y* shall be convertible to T*. 98838fd1498Szrj template<typename _Tp, typename _Yp> 98938fd1498Szrj struct __sp_is_constructible 99038fd1498Szrj : is_convertible<_Yp*, _Tp*>::type 99138fd1498Szrj { }; 99238fd1498Szrj 99338fd1498Szrj 99438fd1498Szrj // Define operator* and operator-> for shared_ptr<T>. 99538fd1498Szrj template<typename _Tp, _Lock_policy _Lp, 99638fd1498Szrj bool = is_array<_Tp>::value, bool = is_void<_Tp>::value> 99738fd1498Szrj class __shared_ptr_access 99838fd1498Szrj { 99938fd1498Szrj public: 100038fd1498Szrj using element_type = _Tp; 100138fd1498Szrj 100238fd1498Szrj element_type& 100338fd1498Szrj operator*() const noexcept 100438fd1498Szrj { 100538fd1498Szrj __glibcxx_assert(_M_get() != nullptr); 100638fd1498Szrj return *_M_get(); 100738fd1498Szrj } 100838fd1498Szrj 100938fd1498Szrj element_type* 101038fd1498Szrj operator->() const noexcept 101138fd1498Szrj { 101238fd1498Szrj _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr); 101338fd1498Szrj return _M_get(); 101438fd1498Szrj } 101538fd1498Szrj 101638fd1498Szrj private: 101738fd1498Szrj element_type* 101838fd1498Szrj _M_get() const noexcept 101938fd1498Szrj { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); } 102038fd1498Szrj }; 102138fd1498Szrj 102238fd1498Szrj // Define operator-> for shared_ptr<cv void>. 102338fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 102438fd1498Szrj class __shared_ptr_access<_Tp, _Lp, false, true> 102538fd1498Szrj { 102638fd1498Szrj public: 102738fd1498Szrj using element_type = _Tp; 102838fd1498Szrj 102938fd1498Szrj element_type* 103038fd1498Szrj operator->() const noexcept 103138fd1498Szrj { 103238fd1498Szrj auto __ptr = static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); 103338fd1498Szrj _GLIBCXX_DEBUG_PEDASSERT(__ptr != nullptr); 103438fd1498Szrj return __ptr; 103538fd1498Szrj } 103638fd1498Szrj }; 103738fd1498Szrj 103838fd1498Szrj // Define operator[] for shared_ptr<T[]> and shared_ptr<T[N]>. 103938fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 104038fd1498Szrj class __shared_ptr_access<_Tp, _Lp, true, false> 104138fd1498Szrj { 104238fd1498Szrj public: 104338fd1498Szrj using element_type = typename remove_extent<_Tp>::type; 104438fd1498Szrj 104538fd1498Szrj #if __cplusplus <= 201402L 104638fd1498Szrj [[__deprecated__("shared_ptr<T[]>::operator* is absent from C++17")]] 104738fd1498Szrj element_type& 104838fd1498Szrj operator*() const noexcept 104938fd1498Szrj { 105038fd1498Szrj __glibcxx_assert(_M_get() != nullptr); 105138fd1498Szrj return *_M_get(); 105238fd1498Szrj } 105338fd1498Szrj 105438fd1498Szrj [[__deprecated__("shared_ptr<T[]>::operator-> is absent from C++17")]] 105538fd1498Szrj element_type* 105638fd1498Szrj operator->() const noexcept 105738fd1498Szrj { 105838fd1498Szrj _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr); 105938fd1498Szrj return _M_get(); 106038fd1498Szrj } 106138fd1498Szrj #endif 106238fd1498Szrj 106338fd1498Szrj element_type& 106438fd1498Szrj operator[](ptrdiff_t __i) const 106538fd1498Szrj { 106638fd1498Szrj __glibcxx_assert(_M_get() != nullptr); 106738fd1498Szrj __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value); 106838fd1498Szrj return _M_get()[__i]; 106938fd1498Szrj } 107038fd1498Szrj 107138fd1498Szrj private: 107238fd1498Szrj element_type* 107338fd1498Szrj _M_get() const noexcept 107438fd1498Szrj { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); } 107538fd1498Szrj }; 107638fd1498Szrj 107738fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 107838fd1498Szrj class __shared_ptr 107938fd1498Szrj : public __shared_ptr_access<_Tp, _Lp> 108038fd1498Szrj { 108138fd1498Szrj public: 108238fd1498Szrj using element_type = typename remove_extent<_Tp>::type; 108338fd1498Szrj 108438fd1498Szrj private: 108538fd1498Szrj // Constraint for taking ownership of a pointer of type _Yp*: 108638fd1498Szrj template<typename _Yp> 108738fd1498Szrj using _SafeConv 108838fd1498Szrj = typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type; 108938fd1498Szrj 109038fd1498Szrj // Constraint for construction from shared_ptr and weak_ptr: 109138fd1498Szrj template<typename _Yp, typename _Res = void> 109238fd1498Szrj using _Compatible = typename 109338fd1498Szrj enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type; 109438fd1498Szrj 109538fd1498Szrj // Constraint for assignment from shared_ptr and weak_ptr: 109638fd1498Szrj template<typename _Yp> 109738fd1498Szrj using _Assignable = _Compatible<_Yp, __shared_ptr&>; 109838fd1498Szrj 109938fd1498Szrj // Constraint for construction from unique_ptr: 110038fd1498Szrj template<typename _Yp, typename _Del, typename _Res = void, 110138fd1498Szrj typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer> 110238fd1498Szrj using _UniqCompatible = typename enable_if<__and_< 110338fd1498Szrj __sp_compatible_with<_Yp*, _Tp*>, is_convertible<_Ptr, element_type*> 110438fd1498Szrj >::value, _Res>::type; 110538fd1498Szrj 110638fd1498Szrj // Constraint for assignment from unique_ptr: 110738fd1498Szrj template<typename _Yp, typename _Del> 110838fd1498Szrj using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>; 110938fd1498Szrj 111038fd1498Szrj public: 111138fd1498Szrj 111238fd1498Szrj #if __cplusplus > 201402L 111338fd1498Szrj using weak_type = __weak_ptr<_Tp, _Lp>; 111438fd1498Szrj #endif 111538fd1498Szrj 111638fd1498Szrj constexpr __shared_ptr() noexcept 111738fd1498Szrj : _M_ptr(0), _M_refcount() 111838fd1498Szrj { } 111938fd1498Szrj 112038fd1498Szrj template<typename _Yp, typename = _SafeConv<_Yp>> 112138fd1498Szrj explicit 112238fd1498Szrj __shared_ptr(_Yp* __p) 112338fd1498Szrj : _M_ptr(__p), _M_refcount(__p, typename is_array<_Tp>::type()) 112438fd1498Szrj { 112538fd1498Szrj static_assert( !is_void<_Yp>::value, "incomplete type" ); 112638fd1498Szrj static_assert( sizeof(_Yp) > 0, "incomplete type" ); 112738fd1498Szrj _M_enable_shared_from_this_with(__p); 112838fd1498Szrj } 112938fd1498Szrj 113038fd1498Szrj template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>> 113138fd1498Szrj __shared_ptr(_Yp* __p, _Deleter __d) 113238fd1498Szrj : _M_ptr(__p), _M_refcount(__p, std::move(__d)) 113338fd1498Szrj { 113438fd1498Szrj static_assert(__is_invocable<_Deleter&, _Yp*&>::value, 113538fd1498Szrj "deleter expression d(p) is well-formed"); 113638fd1498Szrj _M_enable_shared_from_this_with(__p); 113738fd1498Szrj } 113838fd1498Szrj 113938fd1498Szrj template<typename _Yp, typename _Deleter, typename _Alloc, 114038fd1498Szrj typename = _SafeConv<_Yp>> 114138fd1498Szrj __shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a) 114238fd1498Szrj : _M_ptr(__p), _M_refcount(__p, std::move(__d), std::move(__a)) 114338fd1498Szrj { 114438fd1498Szrj static_assert(__is_invocable<_Deleter&, _Yp*&>::value, 114538fd1498Szrj "deleter expression d(p) is well-formed"); 114638fd1498Szrj _M_enable_shared_from_this_with(__p); 114738fd1498Szrj } 114838fd1498Szrj 114938fd1498Szrj template<typename _Deleter> 115038fd1498Szrj __shared_ptr(nullptr_t __p, _Deleter __d) 115138fd1498Szrj : _M_ptr(0), _M_refcount(__p, std::move(__d)) 115238fd1498Szrj { } 115338fd1498Szrj 115438fd1498Szrj template<typename _Deleter, typename _Alloc> 115538fd1498Szrj __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a) 115638fd1498Szrj : _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a)) 115738fd1498Szrj { } 115838fd1498Szrj 115938fd1498Szrj template<typename _Yp> 116038fd1498Szrj __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r, 116138fd1498Szrj element_type* __p) noexcept 116238fd1498Szrj : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws 116338fd1498Szrj { } 116438fd1498Szrj 116538fd1498Szrj __shared_ptr(const __shared_ptr&) noexcept = default; 116638fd1498Szrj __shared_ptr& operator=(const __shared_ptr&) noexcept = default; 116738fd1498Szrj ~__shared_ptr() = default; 116838fd1498Szrj 116938fd1498Szrj template<typename _Yp, typename = _Compatible<_Yp>> 117038fd1498Szrj __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept 117138fd1498Szrj : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) 117238fd1498Szrj { } 117338fd1498Szrj 117438fd1498Szrj __shared_ptr(__shared_ptr&& __r) noexcept 117538fd1498Szrj : _M_ptr(__r._M_ptr), _M_refcount() 117638fd1498Szrj { 117738fd1498Szrj _M_refcount._M_swap(__r._M_refcount); 117838fd1498Szrj __r._M_ptr = 0; 117938fd1498Szrj } 118038fd1498Szrj 118138fd1498Szrj template<typename _Yp, typename = _Compatible<_Yp>> 118238fd1498Szrj __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept 118338fd1498Szrj : _M_ptr(__r._M_ptr), _M_refcount() 118438fd1498Szrj { 118538fd1498Szrj _M_refcount._M_swap(__r._M_refcount); 118638fd1498Szrj __r._M_ptr = 0; 118738fd1498Szrj } 118838fd1498Szrj 118938fd1498Szrj template<typename _Yp, typename = _Compatible<_Yp>> 119038fd1498Szrj explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r) 119138fd1498Szrj : _M_refcount(__r._M_refcount) // may throw 119238fd1498Szrj { 119338fd1498Szrj // It is now safe to copy __r._M_ptr, as 119438fd1498Szrj // _M_refcount(__r._M_refcount) did not throw. 119538fd1498Szrj _M_ptr = __r._M_ptr; 119638fd1498Szrj } 119738fd1498Szrj 119838fd1498Szrj // If an exception is thrown this constructor has no effect. 119938fd1498Szrj template<typename _Yp, typename _Del, 120038fd1498Szrj typename = _UniqCompatible<_Yp, _Del>> 120138fd1498Szrj __shared_ptr(unique_ptr<_Yp, _Del>&& __r) 120238fd1498Szrj : _M_ptr(__r.get()), _M_refcount() 120338fd1498Szrj { 120438fd1498Szrj auto __raw = __to_address(__r.get()); 120538fd1498Szrj _M_refcount = __shared_count<_Lp>(std::move(__r)); 120638fd1498Szrj _M_enable_shared_from_this_with(__raw); 120738fd1498Szrj } 120838fd1498Szrj 120938fd1498Szrj #if __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATED 121038fd1498Szrj protected: 121138fd1498Szrj // If an exception is thrown this constructor has no effect. 121238fd1498Szrj template<typename _Tp1, typename _Del, 121338fd1498Szrj typename enable_if<__and_< 121438fd1498Szrj __not_<is_array<_Tp>>, is_array<_Tp1>, 121538fd1498Szrj is_convertible<typename unique_ptr<_Tp1, _Del>::pointer, _Tp*> 121638fd1498Szrj >::value, bool>::type = true> 121738fd1498Szrj __shared_ptr(unique_ptr<_Tp1, _Del>&& __r, __sp_array_delete) 121838fd1498Szrj : _M_ptr(__r.get()), _M_refcount() 121938fd1498Szrj { 122038fd1498Szrj auto __raw = __to_address(__r.get()); 122138fd1498Szrj _M_refcount = __shared_count<_Lp>(std::move(__r)); 122238fd1498Szrj _M_enable_shared_from_this_with(__raw); 122338fd1498Szrj } 122438fd1498Szrj public: 122538fd1498Szrj #endif 122638fd1498Szrj 122738fd1498Szrj #if _GLIBCXX_USE_DEPRECATED 122838fd1498Szrj #pragma GCC diagnostic push 122938fd1498Szrj #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 123038fd1498Szrj // Postcondition: use_count() == 1 and __r.get() == 0 123138fd1498Szrj template<typename _Yp, typename = _Compatible<_Yp>> 123238fd1498Szrj __shared_ptr(auto_ptr<_Yp>&& __r); 123338fd1498Szrj #pragma GCC diagnostic pop 123438fd1498Szrj #endif 123538fd1498Szrj 123638fd1498Szrj constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { } 123738fd1498Szrj 123838fd1498Szrj template<typename _Yp> 123938fd1498Szrj _Assignable<_Yp> 124038fd1498Szrj operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept 124138fd1498Szrj { 124238fd1498Szrj _M_ptr = __r._M_ptr; 124338fd1498Szrj _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw 124438fd1498Szrj return *this; 124538fd1498Szrj } 124638fd1498Szrj 124738fd1498Szrj #if _GLIBCXX_USE_DEPRECATED 124838fd1498Szrj #pragma GCC diagnostic push 124938fd1498Szrj #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 125038fd1498Szrj template<typename _Yp> 125138fd1498Szrj _Assignable<_Yp> 125238fd1498Szrj operator=(auto_ptr<_Yp>&& __r) 125338fd1498Szrj { 125438fd1498Szrj __shared_ptr(std::move(__r)).swap(*this); 125538fd1498Szrj return *this; 125638fd1498Szrj } 125738fd1498Szrj #pragma GCC diagnostic pop 125838fd1498Szrj #endif 125938fd1498Szrj 126038fd1498Szrj __shared_ptr& 126138fd1498Szrj operator=(__shared_ptr&& __r) noexcept 126238fd1498Szrj { 126338fd1498Szrj __shared_ptr(std::move(__r)).swap(*this); 126438fd1498Szrj return *this; 126538fd1498Szrj } 126638fd1498Szrj 126738fd1498Szrj template<class _Yp> 126838fd1498Szrj _Assignable<_Yp> 126938fd1498Szrj operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept 127038fd1498Szrj { 127138fd1498Szrj __shared_ptr(std::move(__r)).swap(*this); 127238fd1498Szrj return *this; 127338fd1498Szrj } 127438fd1498Szrj 127538fd1498Szrj template<typename _Yp, typename _Del> 127638fd1498Szrj _UniqAssignable<_Yp, _Del> 127738fd1498Szrj operator=(unique_ptr<_Yp, _Del>&& __r) 127838fd1498Szrj { 127938fd1498Szrj __shared_ptr(std::move(__r)).swap(*this); 128038fd1498Szrj return *this; 128138fd1498Szrj } 128238fd1498Szrj 128338fd1498Szrj void 128438fd1498Szrj reset() noexcept 128538fd1498Szrj { __shared_ptr().swap(*this); } 128638fd1498Szrj 128738fd1498Szrj template<typename _Yp> 128838fd1498Szrj _SafeConv<_Yp> 128938fd1498Szrj reset(_Yp* __p) // _Yp must be complete. 129038fd1498Szrj { 129138fd1498Szrj // Catch self-reset errors. 129238fd1498Szrj __glibcxx_assert(__p == 0 || __p != _M_ptr); 129338fd1498Szrj __shared_ptr(__p).swap(*this); 129438fd1498Szrj } 129538fd1498Szrj 129638fd1498Szrj template<typename _Yp, typename _Deleter> 129738fd1498Szrj _SafeConv<_Yp> 129838fd1498Szrj reset(_Yp* __p, _Deleter __d) 129938fd1498Szrj { __shared_ptr(__p, std::move(__d)).swap(*this); } 130038fd1498Szrj 130138fd1498Szrj template<typename _Yp, typename _Deleter, typename _Alloc> 130238fd1498Szrj _SafeConv<_Yp> 130338fd1498Szrj reset(_Yp* __p, _Deleter __d, _Alloc __a) 130438fd1498Szrj { __shared_ptr(__p, std::move(__d), std::move(__a)).swap(*this); } 130538fd1498Szrj 130638fd1498Szrj element_type* 130738fd1498Szrj get() const noexcept 130838fd1498Szrj { return _M_ptr; } 130938fd1498Szrj 131038fd1498Szrj explicit operator bool() const // never throws 131138fd1498Szrj { return _M_ptr == 0 ? false : true; } 131238fd1498Szrj 131338fd1498Szrj bool 131438fd1498Szrj unique() const noexcept 131538fd1498Szrj { return _M_refcount._M_unique(); } 131638fd1498Szrj 131738fd1498Szrj long 131838fd1498Szrj use_count() const noexcept 131938fd1498Szrj { return _M_refcount._M_get_use_count(); } 132038fd1498Szrj 132138fd1498Szrj void 132238fd1498Szrj swap(__shared_ptr<_Tp, _Lp>& __other) noexcept 132338fd1498Szrj { 132438fd1498Szrj std::swap(_M_ptr, __other._M_ptr); 132538fd1498Szrj _M_refcount._M_swap(__other._M_refcount); 132638fd1498Szrj } 132738fd1498Szrj 132838fd1498Szrj template<typename _Tp1> 132938fd1498Szrj bool 133038fd1498Szrj owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept 133138fd1498Szrj { return _M_refcount._M_less(__rhs._M_refcount); } 133238fd1498Szrj 133338fd1498Szrj template<typename _Tp1> 133438fd1498Szrj bool 133538fd1498Szrj owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept 133638fd1498Szrj { return _M_refcount._M_less(__rhs._M_refcount); } 133738fd1498Szrj 133838fd1498Szrj protected: 133938fd1498Szrj // This constructor is non-standard, it is used by allocate_shared. 134038fd1498Szrj template<typename _Alloc, typename... _Args> 1341*58e805e6Szrj __shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args) 1342*58e805e6Szrj : _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...) 1343*58e805e6Szrj { _M_enable_shared_from_this_with(_M_ptr); } 134438fd1498Szrj 134538fd1498Szrj template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc, 134638fd1498Szrj typename... _Args> 134738fd1498Szrj friend __shared_ptr<_Tp1, _Lp1> 134838fd1498Szrj __allocate_shared(const _Alloc& __a, _Args&&... __args); 134938fd1498Szrj 135038fd1498Szrj // This constructor is used by __weak_ptr::lock() and 135138fd1498Szrj // shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t). 135238fd1498Szrj __shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t) 135338fd1498Szrj : _M_refcount(__r._M_refcount, std::nothrow) 135438fd1498Szrj { 135538fd1498Szrj _M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr; 135638fd1498Szrj } 135738fd1498Szrj 135838fd1498Szrj friend class __weak_ptr<_Tp, _Lp>; 135938fd1498Szrj 136038fd1498Szrj private: 136138fd1498Szrj 136238fd1498Szrj template<typename _Yp> 136338fd1498Szrj using __esft_base_t = decltype(__enable_shared_from_this_base( 136438fd1498Szrj std::declval<const __shared_count<_Lp>&>(), 136538fd1498Szrj std::declval<_Yp*>())); 136638fd1498Szrj 136738fd1498Szrj // Detect an accessible and unambiguous enable_shared_from_this base. 136838fd1498Szrj template<typename _Yp, typename = void> 136938fd1498Szrj struct __has_esft_base 137038fd1498Szrj : false_type { }; 137138fd1498Szrj 137238fd1498Szrj template<typename _Yp> 137338fd1498Szrj struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>> 137438fd1498Szrj : __not_<is_array<_Tp>> { }; // No enable shared_from_this for arrays 137538fd1498Szrj 137638fd1498Szrj template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type> 137738fd1498Szrj typename enable_if<__has_esft_base<_Yp2>::value>::type 137838fd1498Szrj _M_enable_shared_from_this_with(_Yp* __p) noexcept 137938fd1498Szrj { 138038fd1498Szrj if (auto __base = __enable_shared_from_this_base(_M_refcount, __p)) 138138fd1498Szrj __base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount); 138238fd1498Szrj } 138338fd1498Szrj 138438fd1498Szrj template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type> 138538fd1498Szrj typename enable_if<!__has_esft_base<_Yp2>::value>::type 138638fd1498Szrj _M_enable_shared_from_this_with(_Yp*) noexcept 138738fd1498Szrj { } 138838fd1498Szrj 138938fd1498Szrj void* 139038fd1498Szrj _M_get_deleter(const std::type_info& __ti) const noexcept 139138fd1498Szrj { return _M_refcount._M_get_deleter(__ti); } 139238fd1498Szrj 139338fd1498Szrj template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr; 139438fd1498Szrj template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr; 139538fd1498Szrj 139638fd1498Szrj template<typename _Del, typename _Tp1, _Lock_policy _Lp1> 139738fd1498Szrj friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept; 139838fd1498Szrj 139938fd1498Szrj template<typename _Del, typename _Tp1> 140038fd1498Szrj friend _Del* get_deleter(const shared_ptr<_Tp1>&) noexcept; 140138fd1498Szrj 140238fd1498Szrj element_type* _M_ptr; // Contained pointer. 140338fd1498Szrj __shared_count<_Lp> _M_refcount; // Reference counter. 140438fd1498Szrj }; 140538fd1498Szrj 140638fd1498Szrj 140738fd1498Szrj // 20.7.2.2.7 shared_ptr comparisons 140838fd1498Szrj template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> 140938fd1498Szrj inline bool 141038fd1498Szrj operator==(const __shared_ptr<_Tp1, _Lp>& __a, 141138fd1498Szrj const __shared_ptr<_Tp2, _Lp>& __b) noexcept 141238fd1498Szrj { return __a.get() == __b.get(); } 141338fd1498Szrj 141438fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 141538fd1498Szrj inline bool 141638fd1498Szrj operator==(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept 141738fd1498Szrj { return !__a; } 141838fd1498Szrj 141938fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 142038fd1498Szrj inline bool 142138fd1498Szrj operator==(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept 142238fd1498Szrj { return !__a; } 142338fd1498Szrj 142438fd1498Szrj template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> 142538fd1498Szrj inline bool 142638fd1498Szrj operator!=(const __shared_ptr<_Tp1, _Lp>& __a, 142738fd1498Szrj const __shared_ptr<_Tp2, _Lp>& __b) noexcept 142838fd1498Szrj { return __a.get() != __b.get(); } 142938fd1498Szrj 143038fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 143138fd1498Szrj inline bool 143238fd1498Szrj operator!=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept 143338fd1498Szrj { return (bool)__a; } 143438fd1498Szrj 143538fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 143638fd1498Szrj inline bool 143738fd1498Szrj operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept 143838fd1498Szrj { return (bool)__a; } 143938fd1498Szrj 144038fd1498Szrj template<typename _Tp, typename _Up, _Lock_policy _Lp> 144138fd1498Szrj inline bool 144238fd1498Szrj operator<(const __shared_ptr<_Tp, _Lp>& __a, 144338fd1498Szrj const __shared_ptr<_Up, _Lp>& __b) noexcept 144438fd1498Szrj { 144538fd1498Szrj using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type; 144638fd1498Szrj using _Up_elt = typename __shared_ptr<_Up, _Lp>::element_type; 144738fd1498Szrj using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type; 144838fd1498Szrj return less<_Vp>()(__a.get(), __b.get()); 144938fd1498Szrj } 145038fd1498Szrj 145138fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 145238fd1498Szrj inline bool 145338fd1498Szrj operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept 145438fd1498Szrj { 145538fd1498Szrj using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type; 145638fd1498Szrj return less<_Tp_elt*>()(__a.get(), nullptr); 145738fd1498Szrj } 145838fd1498Szrj 145938fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 146038fd1498Szrj inline bool 146138fd1498Szrj operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept 146238fd1498Szrj { 146338fd1498Szrj using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type; 146438fd1498Szrj return less<_Tp_elt*>()(nullptr, __a.get()); 146538fd1498Szrj } 146638fd1498Szrj 146738fd1498Szrj template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> 146838fd1498Szrj inline bool 146938fd1498Szrj operator<=(const __shared_ptr<_Tp1, _Lp>& __a, 147038fd1498Szrj const __shared_ptr<_Tp2, _Lp>& __b) noexcept 147138fd1498Szrj { return !(__b < __a); } 147238fd1498Szrj 147338fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 147438fd1498Szrj inline bool 147538fd1498Szrj operator<=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept 147638fd1498Szrj { return !(nullptr < __a); } 147738fd1498Szrj 147838fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 147938fd1498Szrj inline bool 148038fd1498Szrj operator<=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept 148138fd1498Szrj { return !(__a < nullptr); } 148238fd1498Szrj 148338fd1498Szrj template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> 148438fd1498Szrj inline bool 148538fd1498Szrj operator>(const __shared_ptr<_Tp1, _Lp>& __a, 148638fd1498Szrj const __shared_ptr<_Tp2, _Lp>& __b) noexcept 148738fd1498Szrj { return (__b < __a); } 148838fd1498Szrj 148938fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 149038fd1498Szrj inline bool 149138fd1498Szrj operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept 149238fd1498Szrj { return nullptr < __a; } 149338fd1498Szrj 149438fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 149538fd1498Szrj inline bool 149638fd1498Szrj operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept 149738fd1498Szrj { return __a < nullptr; } 149838fd1498Szrj 149938fd1498Szrj template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> 150038fd1498Szrj inline bool 150138fd1498Szrj operator>=(const __shared_ptr<_Tp1, _Lp>& __a, 150238fd1498Szrj const __shared_ptr<_Tp2, _Lp>& __b) noexcept 150338fd1498Szrj { return !(__a < __b); } 150438fd1498Szrj 150538fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 150638fd1498Szrj inline bool 150738fd1498Szrj operator>=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept 150838fd1498Szrj { return !(__a < nullptr); } 150938fd1498Szrj 151038fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 151138fd1498Szrj inline bool 151238fd1498Szrj operator>=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept 151338fd1498Szrj { return !(nullptr < __a); } 151438fd1498Szrj 151538fd1498Szrj template<typename _Sp> 151638fd1498Szrj struct _Sp_less : public binary_function<_Sp, _Sp, bool> 151738fd1498Szrj { 151838fd1498Szrj bool 151938fd1498Szrj operator()(const _Sp& __lhs, const _Sp& __rhs) const noexcept 152038fd1498Szrj { 152138fd1498Szrj typedef typename _Sp::element_type element_type; 152238fd1498Szrj return std::less<element_type*>()(__lhs.get(), __rhs.get()); 152338fd1498Szrj } 152438fd1498Szrj }; 152538fd1498Szrj 152638fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 152738fd1498Szrj struct less<__shared_ptr<_Tp, _Lp>> 152838fd1498Szrj : public _Sp_less<__shared_ptr<_Tp, _Lp>> 152938fd1498Szrj { }; 153038fd1498Szrj 153138fd1498Szrj // 20.7.2.2.8 shared_ptr specialized algorithms. 153238fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 153338fd1498Szrj inline void 153438fd1498Szrj swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) noexcept 153538fd1498Szrj { __a.swap(__b); } 153638fd1498Szrj 153738fd1498Szrj // 20.7.2.2.9 shared_ptr casts 153838fd1498Szrj 153938fd1498Szrj // The seemingly equivalent code: 154038fd1498Szrj // shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get())) 154138fd1498Szrj // will eventually result in undefined behaviour, attempting to 154238fd1498Szrj // delete the same object twice. 154338fd1498Szrj /// static_pointer_cast 154438fd1498Szrj template<typename _Tp, typename _Tp1, _Lock_policy _Lp> 154538fd1498Szrj inline __shared_ptr<_Tp, _Lp> 154638fd1498Szrj static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept 154738fd1498Szrj { 154838fd1498Szrj using _Sp = __shared_ptr<_Tp, _Lp>; 154938fd1498Szrj return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get())); 155038fd1498Szrj } 155138fd1498Szrj 155238fd1498Szrj // The seemingly equivalent code: 155338fd1498Szrj // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get())) 155438fd1498Szrj // will eventually result in undefined behaviour, attempting to 155538fd1498Szrj // delete the same object twice. 155638fd1498Szrj /// const_pointer_cast 155738fd1498Szrj template<typename _Tp, typename _Tp1, _Lock_policy _Lp> 155838fd1498Szrj inline __shared_ptr<_Tp, _Lp> 155938fd1498Szrj const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept 156038fd1498Szrj { 156138fd1498Szrj using _Sp = __shared_ptr<_Tp, _Lp>; 156238fd1498Szrj return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get())); 156338fd1498Szrj } 156438fd1498Szrj 156538fd1498Szrj // The seemingly equivalent code: 156638fd1498Szrj // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get())) 156738fd1498Szrj // will eventually result in undefined behaviour, attempting to 156838fd1498Szrj // delete the same object twice. 156938fd1498Szrj /// dynamic_pointer_cast 157038fd1498Szrj template<typename _Tp, typename _Tp1, _Lock_policy _Lp> 157138fd1498Szrj inline __shared_ptr<_Tp, _Lp> 157238fd1498Szrj dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept 157338fd1498Szrj { 157438fd1498Szrj using _Sp = __shared_ptr<_Tp, _Lp>; 157538fd1498Szrj if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get())) 157638fd1498Szrj return _Sp(__r, __p); 157738fd1498Szrj return _Sp(); 157838fd1498Szrj } 157938fd1498Szrj 158038fd1498Szrj #if __cplusplus > 201402L 158138fd1498Szrj template<typename _Tp, typename _Tp1, _Lock_policy _Lp> 158238fd1498Szrj inline __shared_ptr<_Tp, _Lp> 158338fd1498Szrj reinterpret_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept 158438fd1498Szrj { 158538fd1498Szrj using _Sp = __shared_ptr<_Tp, _Lp>; 158638fd1498Szrj return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get())); 158738fd1498Szrj } 158838fd1498Szrj #endif 158938fd1498Szrj 159038fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 159138fd1498Szrj class __weak_ptr 159238fd1498Szrj { 159338fd1498Szrj template<typename _Yp, typename _Res = void> 159438fd1498Szrj using _Compatible = typename 159538fd1498Szrj enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type; 159638fd1498Szrj 159738fd1498Szrj // Constraint for assignment from shared_ptr and weak_ptr: 159838fd1498Szrj template<typename _Yp> 159938fd1498Szrj using _Assignable = _Compatible<_Yp, __weak_ptr&>; 160038fd1498Szrj 160138fd1498Szrj public: 160238fd1498Szrj using element_type = typename remove_extent<_Tp>::type; 160338fd1498Szrj 160438fd1498Szrj constexpr __weak_ptr() noexcept 160538fd1498Szrj : _M_ptr(nullptr), _M_refcount() 160638fd1498Szrj { } 160738fd1498Szrj 160838fd1498Szrj __weak_ptr(const __weak_ptr&) noexcept = default; 160938fd1498Szrj 161038fd1498Szrj ~__weak_ptr() = default; 161138fd1498Szrj 161238fd1498Szrj // The "obvious" converting constructor implementation: 161338fd1498Szrj // 161438fd1498Szrj // template<typename _Tp1> 161538fd1498Szrj // __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) 161638fd1498Szrj // : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws 161738fd1498Szrj // { } 161838fd1498Szrj // 161938fd1498Szrj // has a serious problem. 162038fd1498Szrj // 162138fd1498Szrj // __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr) 162238fd1498Szrj // conversion may require access to *__r._M_ptr (virtual inheritance). 162338fd1498Szrj // 162438fd1498Szrj // It is not possible to avoid spurious access violations since 162538fd1498Szrj // in multithreaded programs __r._M_ptr may be invalidated at any point. 162638fd1498Szrj template<typename _Yp, typename = _Compatible<_Yp>> 162738fd1498Szrj __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept 162838fd1498Szrj : _M_refcount(__r._M_refcount) 162938fd1498Szrj { _M_ptr = __r.lock().get(); } 163038fd1498Szrj 163138fd1498Szrj template<typename _Yp, typename = _Compatible<_Yp>> 163238fd1498Szrj __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept 163338fd1498Szrj : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) 163438fd1498Szrj { } 163538fd1498Szrj 163638fd1498Szrj __weak_ptr(__weak_ptr&& __r) noexcept 163738fd1498Szrj : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount)) 163838fd1498Szrj { __r._M_ptr = nullptr; } 163938fd1498Szrj 164038fd1498Szrj template<typename _Yp, typename = _Compatible<_Yp>> 164138fd1498Szrj __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept 164238fd1498Szrj : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount)) 164338fd1498Szrj { __r._M_ptr = nullptr; } 164438fd1498Szrj 164538fd1498Szrj __weak_ptr& 164638fd1498Szrj operator=(const __weak_ptr& __r) noexcept = default; 164738fd1498Szrj 164838fd1498Szrj template<typename _Yp> 164938fd1498Szrj _Assignable<_Yp> 165038fd1498Szrj operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept 165138fd1498Szrj { 165238fd1498Szrj _M_ptr = __r.lock().get(); 165338fd1498Szrj _M_refcount = __r._M_refcount; 165438fd1498Szrj return *this; 165538fd1498Szrj } 165638fd1498Szrj 165738fd1498Szrj template<typename _Yp> 165838fd1498Szrj _Assignable<_Yp> 165938fd1498Szrj operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept 166038fd1498Szrj { 166138fd1498Szrj _M_ptr = __r._M_ptr; 166238fd1498Szrj _M_refcount = __r._M_refcount; 166338fd1498Szrj return *this; 166438fd1498Szrj } 166538fd1498Szrj 166638fd1498Szrj __weak_ptr& 166738fd1498Szrj operator=(__weak_ptr&& __r) noexcept 166838fd1498Szrj { 166938fd1498Szrj _M_ptr = __r._M_ptr; 167038fd1498Szrj _M_refcount = std::move(__r._M_refcount); 167138fd1498Szrj __r._M_ptr = nullptr; 167238fd1498Szrj return *this; 167338fd1498Szrj } 167438fd1498Szrj 167538fd1498Szrj template<typename _Yp> 167638fd1498Szrj _Assignable<_Yp> 167738fd1498Szrj operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept 167838fd1498Szrj { 167938fd1498Szrj _M_ptr = __r.lock().get(); 168038fd1498Szrj _M_refcount = std::move(__r._M_refcount); 168138fd1498Szrj __r._M_ptr = nullptr; 168238fd1498Szrj return *this; 168338fd1498Szrj } 168438fd1498Szrj 168538fd1498Szrj __shared_ptr<_Tp, _Lp> 168638fd1498Szrj lock() const noexcept 168738fd1498Szrj { return __shared_ptr<element_type, _Lp>(*this, std::nothrow); } 168838fd1498Szrj 168938fd1498Szrj long 169038fd1498Szrj use_count() const noexcept 169138fd1498Szrj { return _M_refcount._M_get_use_count(); } 169238fd1498Szrj 169338fd1498Szrj bool 169438fd1498Szrj expired() const noexcept 169538fd1498Szrj { return _M_refcount._M_get_use_count() == 0; } 169638fd1498Szrj 169738fd1498Szrj template<typename _Tp1> 169838fd1498Szrj bool 169938fd1498Szrj owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const noexcept 170038fd1498Szrj { return _M_refcount._M_less(__rhs._M_refcount); } 170138fd1498Szrj 170238fd1498Szrj template<typename _Tp1> 170338fd1498Szrj bool 170438fd1498Szrj owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept 170538fd1498Szrj { return _M_refcount._M_less(__rhs._M_refcount); } 170638fd1498Szrj 170738fd1498Szrj void 170838fd1498Szrj reset() noexcept 170938fd1498Szrj { __weak_ptr().swap(*this); } 171038fd1498Szrj 171138fd1498Szrj void 171238fd1498Szrj swap(__weak_ptr& __s) noexcept 171338fd1498Szrj { 171438fd1498Szrj std::swap(_M_ptr, __s._M_ptr); 171538fd1498Szrj _M_refcount._M_swap(__s._M_refcount); 171638fd1498Szrj } 171738fd1498Szrj 171838fd1498Szrj private: 171938fd1498Szrj // Used by __enable_shared_from_this. 172038fd1498Szrj void 172138fd1498Szrj _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) noexcept 172238fd1498Szrj { 172338fd1498Szrj if (use_count() == 0) 172438fd1498Szrj { 172538fd1498Szrj _M_ptr = __ptr; 172638fd1498Szrj _M_refcount = __refcount; 172738fd1498Szrj } 172838fd1498Szrj } 172938fd1498Szrj 173038fd1498Szrj template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr; 173138fd1498Szrj template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr; 173238fd1498Szrj friend class __enable_shared_from_this<_Tp, _Lp>; 173338fd1498Szrj friend class enable_shared_from_this<_Tp>; 173438fd1498Szrj 173538fd1498Szrj element_type* _M_ptr; // Contained pointer. 173638fd1498Szrj __weak_count<_Lp> _M_refcount; // Reference counter. 173738fd1498Szrj }; 173838fd1498Szrj 173938fd1498Szrj // 20.7.2.3.6 weak_ptr specialized algorithms. 174038fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 174138fd1498Szrj inline void 174238fd1498Szrj swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) noexcept 174338fd1498Szrj { __a.swap(__b); } 174438fd1498Szrj 174538fd1498Szrj template<typename _Tp, typename _Tp1> 174638fd1498Szrj struct _Sp_owner_less : public binary_function<_Tp, _Tp, bool> 174738fd1498Szrj { 174838fd1498Szrj bool 174938fd1498Szrj operator()(const _Tp& __lhs, const _Tp& __rhs) const noexcept 175038fd1498Szrj { return __lhs.owner_before(__rhs); } 175138fd1498Szrj 175238fd1498Szrj bool 175338fd1498Szrj operator()(const _Tp& __lhs, const _Tp1& __rhs) const noexcept 175438fd1498Szrj { return __lhs.owner_before(__rhs); } 175538fd1498Szrj 175638fd1498Szrj bool 175738fd1498Szrj operator()(const _Tp1& __lhs, const _Tp& __rhs) const noexcept 175838fd1498Szrj { return __lhs.owner_before(__rhs); } 175938fd1498Szrj }; 176038fd1498Szrj 176138fd1498Szrj template<> 176238fd1498Szrj struct _Sp_owner_less<void, void> 176338fd1498Szrj { 176438fd1498Szrj template<typename _Tp, typename _Up> 176538fd1498Szrj auto 176638fd1498Szrj operator()(const _Tp& __lhs, const _Up& __rhs) const noexcept 176738fd1498Szrj -> decltype(__lhs.owner_before(__rhs)) 176838fd1498Szrj { return __lhs.owner_before(__rhs); } 176938fd1498Szrj 177038fd1498Szrj using is_transparent = void; 177138fd1498Szrj }; 177238fd1498Szrj 177338fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 177438fd1498Szrj struct owner_less<__shared_ptr<_Tp, _Lp>> 177538fd1498Szrj : public _Sp_owner_less<__shared_ptr<_Tp, _Lp>, __weak_ptr<_Tp, _Lp>> 177638fd1498Szrj { }; 177738fd1498Szrj 177838fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 177938fd1498Szrj struct owner_less<__weak_ptr<_Tp, _Lp>> 178038fd1498Szrj : public _Sp_owner_less<__weak_ptr<_Tp, _Lp>, __shared_ptr<_Tp, _Lp>> 178138fd1498Szrj { }; 178238fd1498Szrj 178338fd1498Szrj 178438fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 178538fd1498Szrj class __enable_shared_from_this 178638fd1498Szrj { 178738fd1498Szrj protected: 178838fd1498Szrj constexpr __enable_shared_from_this() noexcept { } 178938fd1498Szrj 179038fd1498Szrj __enable_shared_from_this(const __enable_shared_from_this&) noexcept { } 179138fd1498Szrj 179238fd1498Szrj __enable_shared_from_this& 179338fd1498Szrj operator=(const __enable_shared_from_this&) noexcept 179438fd1498Szrj { return *this; } 179538fd1498Szrj 179638fd1498Szrj ~__enable_shared_from_this() { } 179738fd1498Szrj 179838fd1498Szrj public: 179938fd1498Szrj __shared_ptr<_Tp, _Lp> 180038fd1498Szrj shared_from_this() 180138fd1498Szrj { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); } 180238fd1498Szrj 180338fd1498Szrj __shared_ptr<const _Tp, _Lp> 180438fd1498Szrj shared_from_this() const 180538fd1498Szrj { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); } 180638fd1498Szrj 180738fd1498Szrj #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 180838fd1498Szrj __weak_ptr<_Tp, _Lp> 180938fd1498Szrj weak_from_this() noexcept 181038fd1498Szrj { return this->_M_weak_this; } 181138fd1498Szrj 181238fd1498Szrj __weak_ptr<const _Tp, _Lp> 181338fd1498Szrj weak_from_this() const noexcept 181438fd1498Szrj { return this->_M_weak_this; } 181538fd1498Szrj #endif 181638fd1498Szrj 181738fd1498Szrj private: 181838fd1498Szrj template<typename _Tp1> 181938fd1498Szrj void 182038fd1498Szrj _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const noexcept 182138fd1498Szrj { _M_weak_this._M_assign(__p, __n); } 182238fd1498Szrj 182338fd1498Szrj friend const __enable_shared_from_this* 182438fd1498Szrj __enable_shared_from_this_base(const __shared_count<_Lp>&, 182538fd1498Szrj const __enable_shared_from_this* __p) 182638fd1498Szrj { return __p; } 182738fd1498Szrj 182838fd1498Szrj template<typename, _Lock_policy> 182938fd1498Szrj friend class __shared_ptr; 183038fd1498Szrj 183138fd1498Szrj mutable __weak_ptr<_Tp, _Lp> _M_weak_this; 183238fd1498Szrj }; 183338fd1498Szrj 183438fd1498Szrj template<typename _Tp, _Lock_policy _Lp, typename _Alloc, typename... _Args> 183538fd1498Szrj inline __shared_ptr<_Tp, _Lp> 183638fd1498Szrj __allocate_shared(const _Alloc& __a, _Args&&... __args) 183738fd1498Szrj { 1838*58e805e6Szrj return __shared_ptr<_Tp, _Lp>(_Sp_alloc_shared_tag<_Alloc>{__a}, 183938fd1498Szrj std::forward<_Args>(__args)...); 184038fd1498Szrj } 184138fd1498Szrj 184238fd1498Szrj template<typename _Tp, _Lock_policy _Lp, typename... _Args> 184338fd1498Szrj inline __shared_ptr<_Tp, _Lp> 184438fd1498Szrj __make_shared(_Args&&... __args) 184538fd1498Szrj { 184638fd1498Szrj typedef typename std::remove_const<_Tp>::type _Tp_nc; 184738fd1498Szrj return std::__allocate_shared<_Tp, _Lp>(std::allocator<_Tp_nc>(), 184838fd1498Szrj std::forward<_Args>(__args)...); 184938fd1498Szrj } 185038fd1498Szrj 185138fd1498Szrj /// std::hash specialization for __shared_ptr. 185238fd1498Szrj template<typename _Tp, _Lock_policy _Lp> 185338fd1498Szrj struct hash<__shared_ptr<_Tp, _Lp>> 185438fd1498Szrj : public __hash_base<size_t, __shared_ptr<_Tp, _Lp>> 185538fd1498Szrj { 185638fd1498Szrj size_t 185738fd1498Szrj operator()(const __shared_ptr<_Tp, _Lp>& __s) const noexcept 185838fd1498Szrj { 185938fd1498Szrj return hash<typename __shared_ptr<_Tp, _Lp>::element_type*>()( 186038fd1498Szrj __s.get()); 186138fd1498Szrj } 186238fd1498Szrj }; 186338fd1498Szrj 186438fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION 186538fd1498Szrj } // namespace 186638fd1498Szrj 186738fd1498Szrj #endif // _SHARED_PTR_BASE_H 1868