xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/bits/shared_ptr_base.h (revision 95059079af47f9a66a175f374f2da1a5020e3255)
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 
_GLIBCXX_VISIBILITY(default)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