xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/include/bits/shared_ptr_base.h (revision 0a8dc9fc45f4d0b236341a473fac4a486375f60c)
1e4b17023SJohn Marino // shared_ptr and weak_ptr implementation details -*- C++ -*-
2e4b17023SJohn Marino 
3e4b17023SJohn Marino // Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
4e4b17023SJohn Marino // Free Software Foundation, Inc.
5e4b17023SJohn Marino //
6e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library.  This library is free
7e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the
8e4b17023SJohn Marino // terms of the GNU General Public License as published by the
9e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option)
10e4b17023SJohn Marino // any later version.
11e4b17023SJohn Marino 
12e4b17023SJohn Marino // This library is distributed in the hope that it will be useful,
13e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of
14e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15e4b17023SJohn Marino // GNU General Public License for more details.
16e4b17023SJohn Marino 
17e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional
18e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version
19e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation.
20e4b17023SJohn Marino 
21e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and
22e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program;
23e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24e4b17023SJohn Marino // <http://www.gnu.org/licenses/>.
25e4b17023SJohn Marino 
26e4b17023SJohn Marino // GCC Note: Based on files from version 1.32.0 of the Boost library.
27e4b17023SJohn Marino 
28e4b17023SJohn Marino //  shared_count.hpp
29e4b17023SJohn Marino //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
30e4b17023SJohn Marino 
31e4b17023SJohn Marino //  shared_ptr.hpp
32e4b17023SJohn Marino //  Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
33e4b17023SJohn Marino //  Copyright (C) 2001, 2002, 2003 Peter Dimov
34e4b17023SJohn Marino 
35e4b17023SJohn Marino //  weak_ptr.hpp
36e4b17023SJohn Marino //  Copyright (C) 2001, 2002, 2003 Peter Dimov
37e4b17023SJohn Marino 
38e4b17023SJohn Marino //  enable_shared_from_this.hpp
39e4b17023SJohn Marino //  Copyright (C) 2002 Peter Dimov
40e4b17023SJohn Marino 
41e4b17023SJohn Marino // Distributed under the Boost Software License, Version 1.0. (See
42e4b17023SJohn Marino // accompanying file LICENSE_1_0.txt or copy at
43e4b17023SJohn Marino // http://www.boost.org/LICENSE_1_0.txt)
44e4b17023SJohn Marino 
45e4b17023SJohn Marino /** @file bits/shared_ptr_base.h
46e4b17023SJohn Marino  *  This is an internal header file, included by other library headers.
47e4b17023SJohn Marino  *  Do not attempt to use it directly. @headername{memory}
48e4b17023SJohn Marino  */
49e4b17023SJohn Marino 
50e4b17023SJohn Marino #ifndef _SHARED_PTR_BASE_H
51e4b17023SJohn Marino #define _SHARED_PTR_BASE_H 1
52e4b17023SJohn Marino 
_GLIBCXX_VISIBILITY(default)53e4b17023SJohn Marino namespace std _GLIBCXX_VISIBILITY(default)
54e4b17023SJohn Marino {
55e4b17023SJohn Marino _GLIBCXX_BEGIN_NAMESPACE_VERSION
56e4b17023SJohn Marino 
57e4b17023SJohn Marino  /**
58e4b17023SJohn Marino    *  @brief  Exception possibly thrown by @c shared_ptr.
59e4b17023SJohn Marino    *  @ingroup exceptions
60e4b17023SJohn Marino    */
61e4b17023SJohn Marino   class bad_weak_ptr : public std::exception
62e4b17023SJohn Marino   {
63e4b17023SJohn Marino   public:
64e4b17023SJohn Marino     virtual char const*
65e4b17023SJohn Marino     what() const noexcept;
66e4b17023SJohn Marino 
67e4b17023SJohn Marino     virtual ~bad_weak_ptr() noexcept;
68e4b17023SJohn Marino   };
69e4b17023SJohn Marino 
70e4b17023SJohn Marino   // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
71e4b17023SJohn Marino   inline void
72e4b17023SJohn Marino   __throw_bad_weak_ptr()
73e4b17023SJohn Marino   {
74e4b17023SJohn Marino #if __EXCEPTIONS
75e4b17023SJohn Marino     throw bad_weak_ptr();
76e4b17023SJohn Marino #else
77e4b17023SJohn Marino     __builtin_abort();
78e4b17023SJohn Marino #endif
79e4b17023SJohn Marino   }
80e4b17023SJohn Marino 
81e4b17023SJohn Marino   using __gnu_cxx::_Lock_policy;
82e4b17023SJohn Marino   using __gnu_cxx::__default_lock_policy;
83e4b17023SJohn Marino   using __gnu_cxx::_S_single;
84e4b17023SJohn Marino   using __gnu_cxx::_S_mutex;
85e4b17023SJohn Marino   using __gnu_cxx::_S_atomic;
86e4b17023SJohn Marino 
87e4b17023SJohn Marino   // Empty helper class except when the template argument is _S_mutex.
88e4b17023SJohn Marino   template<_Lock_policy _Lp>
89e4b17023SJohn Marino     class _Mutex_base
90e4b17023SJohn Marino     {
91e4b17023SJohn Marino     protected:
92e4b17023SJohn Marino       // The atomic policy uses fully-fenced builtins, single doesn't care.
93e4b17023SJohn Marino       enum { _S_need_barriers = 0 };
94e4b17023SJohn Marino     };
95e4b17023SJohn Marino 
96e4b17023SJohn Marino   template<>
97e4b17023SJohn Marino     class _Mutex_base<_S_mutex>
98e4b17023SJohn Marino     : public __gnu_cxx::__mutex
99e4b17023SJohn Marino     {
100e4b17023SJohn Marino     protected:
101e4b17023SJohn Marino       // This policy is used when atomic builtins are not available.
102e4b17023SJohn Marino       // The replacement atomic operations might not have the necessary
103e4b17023SJohn Marino       // memory barriers.
104e4b17023SJohn Marino       enum { _S_need_barriers = 1 };
105e4b17023SJohn Marino     };
106e4b17023SJohn Marino 
107e4b17023SJohn Marino   template<_Lock_policy _Lp = __default_lock_policy>
108e4b17023SJohn Marino     class _Sp_counted_base
109e4b17023SJohn Marino     : public _Mutex_base<_Lp>
110e4b17023SJohn Marino     {
111e4b17023SJohn Marino     public:
112e4b17023SJohn Marino       _Sp_counted_base() noexcept
113e4b17023SJohn Marino       : _M_use_count(1), _M_weak_count(1) { }
114e4b17023SJohn Marino 
115e4b17023SJohn Marino       virtual
116e4b17023SJohn Marino       ~_Sp_counted_base() noexcept
117e4b17023SJohn Marino       { }
118e4b17023SJohn Marino 
119e4b17023SJohn Marino       // Called when _M_use_count drops to zero, to release the resources
120e4b17023SJohn Marino       // managed by *this.
121e4b17023SJohn Marino       virtual void
122e4b17023SJohn Marino       _M_dispose() noexcept = 0;
123e4b17023SJohn Marino 
124e4b17023SJohn Marino       // Called when _M_weak_count drops to zero.
125e4b17023SJohn Marino       virtual void
126e4b17023SJohn Marino       _M_destroy() noexcept
127e4b17023SJohn Marino       { delete this; }
128e4b17023SJohn Marino 
129e4b17023SJohn Marino       virtual void*
130e4b17023SJohn Marino       _M_get_deleter(const std::type_info&) = 0;
131e4b17023SJohn Marino 
132e4b17023SJohn Marino       void
133e4b17023SJohn Marino       _M_add_ref_copy()
134e4b17023SJohn Marino       { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
135e4b17023SJohn Marino 
136e4b17023SJohn Marino       void
137e4b17023SJohn Marino       _M_add_ref_lock();
138e4b17023SJohn Marino 
139e4b17023SJohn Marino       void
140e4b17023SJohn Marino       _M_release() noexcept
141e4b17023SJohn Marino       {
142e4b17023SJohn Marino         // Be race-detector-friendly.  For more info see bits/c++config.
143e4b17023SJohn Marino         _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
144e4b17023SJohn Marino 	if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
145e4b17023SJohn Marino 	  {
146e4b17023SJohn Marino             _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
147e4b17023SJohn Marino 	    _M_dispose();
148e4b17023SJohn Marino 	    // There must be a memory barrier between dispose() and destroy()
149e4b17023SJohn Marino 	    // to ensure that the effects of dispose() are observed in the
150e4b17023SJohn Marino 	    // thread that runs destroy().
151e4b17023SJohn Marino 	    // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
152e4b17023SJohn Marino 	    if (_Mutex_base<_Lp>::_S_need_barriers)
153e4b17023SJohn Marino 	      {
154e4b17023SJohn Marino 	        _GLIBCXX_READ_MEM_BARRIER;
155e4b17023SJohn Marino 	        _GLIBCXX_WRITE_MEM_BARRIER;
156e4b17023SJohn Marino 	      }
157e4b17023SJohn Marino 
158e4b17023SJohn Marino             // Be race-detector-friendly.  For more info see bits/c++config.
159e4b17023SJohn Marino             _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
160e4b17023SJohn Marino 	    if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
161e4b17023SJohn Marino 						       -1) == 1)
162e4b17023SJohn Marino               {
163e4b17023SJohn Marino                 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
164e4b17023SJohn Marino 	        _M_destroy();
165e4b17023SJohn Marino               }
166e4b17023SJohn Marino 	  }
167e4b17023SJohn Marino       }
168e4b17023SJohn Marino 
169e4b17023SJohn Marino       void
170e4b17023SJohn Marino       _M_weak_add_ref() noexcept
171e4b17023SJohn Marino       { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
172e4b17023SJohn Marino 
173e4b17023SJohn Marino       void
174e4b17023SJohn Marino       _M_weak_release() noexcept
175e4b17023SJohn Marino       {
176e4b17023SJohn Marino         // Be race-detector-friendly. For more info see bits/c++config.
177e4b17023SJohn Marino         _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
178e4b17023SJohn Marino 	if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
179e4b17023SJohn Marino 	  {
180e4b17023SJohn Marino             _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
181e4b17023SJohn Marino 	    if (_Mutex_base<_Lp>::_S_need_barriers)
182e4b17023SJohn Marino 	      {
183e4b17023SJohn Marino 	        // See _M_release(),
184e4b17023SJohn Marino 	        // destroy() must observe results of dispose()
185e4b17023SJohn Marino 	        _GLIBCXX_READ_MEM_BARRIER;
186e4b17023SJohn Marino 	        _GLIBCXX_WRITE_MEM_BARRIER;
187e4b17023SJohn Marino 	      }
188e4b17023SJohn Marino 	    _M_destroy();
189e4b17023SJohn Marino 	  }
190e4b17023SJohn Marino       }
191e4b17023SJohn Marino 
192e4b17023SJohn Marino       long
193e4b17023SJohn Marino       _M_get_use_count() const noexcept
194e4b17023SJohn Marino       {
195e4b17023SJohn Marino         // No memory barrier is used here so there is no synchronization
196e4b17023SJohn Marino         // with other threads.
197e4b17023SJohn Marino         return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED);
198e4b17023SJohn Marino       }
199e4b17023SJohn Marino 
200e4b17023SJohn Marino     private:
201e4b17023SJohn Marino       _Sp_counted_base(_Sp_counted_base const&) = delete;
202e4b17023SJohn Marino       _Sp_counted_base& operator=(_Sp_counted_base const&) = delete;
203e4b17023SJohn Marino 
204e4b17023SJohn Marino       _Atomic_word  _M_use_count;     // #shared
205e4b17023SJohn Marino       _Atomic_word  _M_weak_count;    // #weak + (#shared != 0)
206e4b17023SJohn Marino     };
207e4b17023SJohn Marino 
208e4b17023SJohn Marino   template<>
209e4b17023SJohn Marino     inline void
210e4b17023SJohn Marino     _Sp_counted_base<_S_single>::
211e4b17023SJohn Marino     _M_add_ref_lock()
212e4b17023SJohn Marino     {
213e4b17023SJohn Marino       if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
214e4b17023SJohn Marino 	{
215e4b17023SJohn Marino 	  _M_use_count = 0;
216e4b17023SJohn Marino 	  __throw_bad_weak_ptr();
217e4b17023SJohn Marino 	}
218e4b17023SJohn Marino     }
219e4b17023SJohn Marino 
220e4b17023SJohn Marino   template<>
221e4b17023SJohn Marino     inline void
222e4b17023SJohn Marino     _Sp_counted_base<_S_mutex>::
223e4b17023SJohn Marino     _M_add_ref_lock()
224e4b17023SJohn Marino     {
225e4b17023SJohn Marino       __gnu_cxx::__scoped_lock sentry(*this);
226e4b17023SJohn Marino       if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
227e4b17023SJohn Marino 	{
228e4b17023SJohn Marino 	  _M_use_count = 0;
229e4b17023SJohn Marino 	  __throw_bad_weak_ptr();
230e4b17023SJohn Marino 	}
231e4b17023SJohn Marino     }
232e4b17023SJohn Marino 
233e4b17023SJohn Marino   template<>
234e4b17023SJohn Marino     inline void
235e4b17023SJohn Marino     _Sp_counted_base<_S_atomic>::
236e4b17023SJohn Marino     _M_add_ref_lock()
237e4b17023SJohn Marino     {
238e4b17023SJohn Marino       // Perform lock-free add-if-not-zero operation.
239e4b17023SJohn Marino       _Atomic_word __count = _M_use_count;
240e4b17023SJohn Marino       do
241e4b17023SJohn Marino 	{
242e4b17023SJohn Marino 	  if (__count == 0)
243e4b17023SJohn Marino 	    __throw_bad_weak_ptr();
244e4b17023SJohn Marino 	  // Replace the current counter value with the old value + 1, as
245e4b17023SJohn Marino 	  // long as it's not changed meanwhile.
246e4b17023SJohn Marino 	}
247e4b17023SJohn Marino       while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
248e4b17023SJohn Marino 					  true, __ATOMIC_ACQ_REL,
249e4b17023SJohn Marino 					  __ATOMIC_RELAXED));
250e4b17023SJohn Marino     }
251e4b17023SJohn Marino 
252e4b17023SJohn Marino 
253e4b17023SJohn Marino   // Forward declarations.
254e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
255e4b17023SJohn Marino     class __shared_ptr;
256e4b17023SJohn Marino 
257e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
258e4b17023SJohn Marino     class __weak_ptr;
259e4b17023SJohn Marino 
260e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
261e4b17023SJohn Marino     class __enable_shared_from_this;
262e4b17023SJohn Marino 
263e4b17023SJohn Marino   template<typename _Tp>
264e4b17023SJohn Marino     class shared_ptr;
265e4b17023SJohn Marino 
266e4b17023SJohn Marino   template<typename _Tp>
267e4b17023SJohn Marino     class weak_ptr;
268e4b17023SJohn Marino 
269e4b17023SJohn Marino   template<typename _Tp>
270e4b17023SJohn Marino     struct owner_less;
271e4b17023SJohn Marino 
272e4b17023SJohn Marino   template<typename _Tp>
273e4b17023SJohn Marino     class enable_shared_from_this;
274e4b17023SJohn Marino 
275e4b17023SJohn Marino   template<_Lock_policy _Lp = __default_lock_policy>
276e4b17023SJohn Marino     class __weak_count;
277e4b17023SJohn Marino 
278e4b17023SJohn Marino   template<_Lock_policy _Lp = __default_lock_policy>
279e4b17023SJohn Marino     class __shared_count;
280e4b17023SJohn Marino 
281e4b17023SJohn Marino 
282e4b17023SJohn Marino   // Counted ptr with no deleter or allocator support
283e4b17023SJohn Marino   template<typename _Ptr, _Lock_policy _Lp>
284e4b17023SJohn Marino     class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>
285e4b17023SJohn Marino     {
286e4b17023SJohn Marino     public:
287e4b17023SJohn Marino       explicit
288e4b17023SJohn Marino       _Sp_counted_ptr(_Ptr __p)
289e4b17023SJohn Marino       : _M_ptr(__p) { }
290e4b17023SJohn Marino 
291e4b17023SJohn Marino       virtual void
292e4b17023SJohn Marino       _M_dispose() noexcept
293e4b17023SJohn Marino       { delete _M_ptr; }
294e4b17023SJohn Marino 
295e4b17023SJohn Marino       virtual void
296e4b17023SJohn Marino       _M_destroy() noexcept
297e4b17023SJohn Marino       { delete this; }
298e4b17023SJohn Marino 
299e4b17023SJohn Marino       virtual void*
300e4b17023SJohn Marino       _M_get_deleter(const std::type_info&)
301e4b17023SJohn Marino       { return 0; }
302e4b17023SJohn Marino 
303e4b17023SJohn Marino       _Sp_counted_ptr(const _Sp_counted_ptr&) = delete;
304e4b17023SJohn Marino       _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete;
305e4b17023SJohn Marino 
306e4b17023SJohn Marino     protected:
307e4b17023SJohn Marino       _Ptr             _M_ptr;  // copy constructor must not throw
308e4b17023SJohn Marino     };
309e4b17023SJohn Marino 
310e4b17023SJohn Marino   template<>
311e4b17023SJohn Marino     inline void
312e4b17023SJohn Marino     _Sp_counted_ptr<nullptr_t, _S_single>::_M_dispose() noexcept { }
313e4b17023SJohn Marino 
314e4b17023SJohn Marino   template<>
315e4b17023SJohn Marino     inline void
316e4b17023SJohn Marino     _Sp_counted_ptr<nullptr_t, _S_mutex>::_M_dispose() noexcept { }
317e4b17023SJohn Marino 
318e4b17023SJohn Marino   template<>
319e4b17023SJohn Marino     inline void
320e4b17023SJohn Marino     _Sp_counted_ptr<nullptr_t, _S_atomic>::_M_dispose() noexcept { }
321e4b17023SJohn Marino 
322e4b17023SJohn Marino   // Support for custom deleter and/or allocator
323e4b17023SJohn Marino   template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp>
324e4b17023SJohn Marino     class _Sp_counted_deleter final : public _Sp_counted_base<_Lp>
325e4b17023SJohn Marino     {
326e4b17023SJohn Marino       // Helper class that stores the Deleter and also acts as an allocator.
327e4b17023SJohn Marino       // Used to dispose of the owned pointer and the internal refcount
328e4b17023SJohn Marino       // Requires that copies of _Alloc can free each other's memory.
329e4b17023SJohn Marino       struct _My_Deleter
330e4b17023SJohn Marino       : public _Alloc           // copy constructor must not throw
331e4b17023SJohn Marino       {
332e4b17023SJohn Marino 	_Deleter _M_del;        // copy constructor must not throw
333e4b17023SJohn Marino 	_My_Deleter(_Deleter __d, const _Alloc& __a)
334e4b17023SJohn Marino 	: _Alloc(__a), _M_del(__d) { }
335e4b17023SJohn Marino       };
336e4b17023SJohn Marino 
337e4b17023SJohn Marino     public:
338e4b17023SJohn Marino       // __d(__p) must not throw.
339e4b17023SJohn Marino       _Sp_counted_deleter(_Ptr __p, _Deleter __d)
340e4b17023SJohn Marino       : _M_ptr(__p), _M_del(__d, _Alloc()) { }
341e4b17023SJohn Marino 
342e4b17023SJohn Marino       // __d(__p) must not throw.
343e4b17023SJohn Marino       _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a)
344e4b17023SJohn Marino       : _M_ptr(__p), _M_del(__d, __a) { }
345e4b17023SJohn Marino 
346e4b17023SJohn Marino       ~_Sp_counted_deleter() noexcept { }
347e4b17023SJohn Marino 
348e4b17023SJohn Marino       virtual void
349e4b17023SJohn Marino       _M_dispose() noexcept
350e4b17023SJohn Marino       { _M_del._M_del(_M_ptr); }
351e4b17023SJohn Marino 
352e4b17023SJohn Marino       virtual void
353e4b17023SJohn Marino       _M_destroy() noexcept
354e4b17023SJohn Marino       {
355e4b17023SJohn Marino 	typedef typename allocator_traits<_Alloc>::template
356e4b17023SJohn Marino 	  rebind_traits<_Sp_counted_deleter> _Alloc_traits;
357e4b17023SJohn Marino 	typename _Alloc_traits::allocator_type __a(_M_del);
358e4b17023SJohn Marino 	_Alloc_traits::destroy(__a, this);
359e4b17023SJohn Marino 	_Alloc_traits::deallocate(__a, this, 1);
360e4b17023SJohn Marino       }
361e4b17023SJohn Marino 
362e4b17023SJohn Marino       virtual void*
363e4b17023SJohn Marino       _M_get_deleter(const std::type_info& __ti)
364e4b17023SJohn Marino       {
365e4b17023SJohn Marino #ifdef __GXX_RTTI
366e4b17023SJohn Marino         return __ti == typeid(_Deleter) ? &_M_del._M_del : 0;
367e4b17023SJohn Marino #else
368e4b17023SJohn Marino         return 0;
369e4b17023SJohn Marino #endif
370e4b17023SJohn Marino       }
371e4b17023SJohn Marino 
372e4b17023SJohn Marino     protected:
373e4b17023SJohn Marino       _Ptr             _M_ptr;  // copy constructor must not throw
374e4b17023SJohn Marino       _My_Deleter      _M_del;  // copy constructor must not throw
375e4b17023SJohn Marino     };
376e4b17023SJohn Marino 
377e4b17023SJohn Marino   // helpers for make_shared / allocate_shared
378e4b17023SJohn Marino 
379e4b17023SJohn Marino   struct _Sp_make_shared_tag { };
380e4b17023SJohn Marino 
381e4b17023SJohn Marino   template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
382e4b17023SJohn Marino     class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp>
383e4b17023SJohn Marino     {
384e4b17023SJohn Marino       // Helper class that stores the pointer and also acts as an allocator.
385e4b17023SJohn Marino       // Used to dispose of the owned pointer and the internal refcount
386e4b17023SJohn Marino       // Requires that copies of _Alloc can free each other's memory.
387e4b17023SJohn Marino       struct _Impl
388e4b17023SJohn Marino       : public _Alloc           // copy constructor must not throw
389e4b17023SJohn Marino       {
390e4b17023SJohn Marino 	_Impl(_Alloc __a) : _Alloc(__a), _M_ptr() { }
391e4b17023SJohn Marino 	_Tp* _M_ptr;
392e4b17023SJohn Marino       };
393e4b17023SJohn Marino 
394e4b17023SJohn Marino     public:
395e4b17023SJohn Marino       template<typename... _Args>
396e4b17023SJohn Marino 	_Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args)
397*95d28233SJohn Marino 	: _M_impl(__a)
398e4b17023SJohn Marino 	{
399e4b17023SJohn Marino 	  _M_impl._M_ptr = static_cast<_Tp*>(static_cast<void*>(&_M_storage));
400e4b17023SJohn Marino 	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
401e4b17023SJohn Marino 	  // 2070.  allocate_shared should use allocator_traits<A>::construct
402e4b17023SJohn Marino 	  allocator_traits<_Alloc>::construct(__a, _M_impl._M_ptr,
403e4b17023SJohn Marino 	      std::forward<_Args>(__args)...); // might throw
404e4b17023SJohn Marino 	}
405e4b17023SJohn Marino 
406e4b17023SJohn Marino       ~_Sp_counted_ptr_inplace() noexcept { }
407e4b17023SJohn Marino 
408e4b17023SJohn Marino       virtual void
409e4b17023SJohn Marino       _M_dispose() noexcept
410e4b17023SJohn Marino       { allocator_traits<_Alloc>::destroy(_M_impl, _M_impl._M_ptr); }
411e4b17023SJohn Marino 
412e4b17023SJohn Marino       // Override because the allocator needs to know the dynamic type
413e4b17023SJohn Marino       virtual void
414e4b17023SJohn Marino       _M_destroy() noexcept
415e4b17023SJohn Marino       {
416e4b17023SJohn Marino 	typedef typename allocator_traits<_Alloc>::template
417e4b17023SJohn Marino 	  rebind_traits<_Sp_counted_ptr_inplace> _Alloc_traits;
418e4b17023SJohn Marino 	typename _Alloc_traits::allocator_type __a(_M_impl);
419e4b17023SJohn Marino 	_Alloc_traits::destroy(__a, this);
420e4b17023SJohn Marino 	_Alloc_traits::deallocate(__a, this, 1);
421e4b17023SJohn Marino       }
422e4b17023SJohn Marino 
423e4b17023SJohn Marino       // Sneaky trick so __shared_ptr can get the managed pointer
424e4b17023SJohn Marino       virtual void*
425e4b17023SJohn Marino       _M_get_deleter(const std::type_info& __ti) noexcept
426e4b17023SJohn Marino       {
427e4b17023SJohn Marino #ifdef __GXX_RTTI
428e4b17023SJohn Marino 	return __ti == typeid(_Sp_make_shared_tag)
429e4b17023SJohn Marino 	       ? static_cast<void*>(&_M_storage)
430e4b17023SJohn Marino 	       : 0;
431e4b17023SJohn Marino #else
432e4b17023SJohn Marino         return 0;
433e4b17023SJohn Marino #endif
434e4b17023SJohn Marino       }
435e4b17023SJohn Marino 
436e4b17023SJohn Marino     private:
437e4b17023SJohn Marino       _Impl _M_impl;
438e4b17023SJohn Marino       typename aligned_storage<sizeof(_Tp), alignment_of<_Tp>::value>::type
439e4b17023SJohn Marino 	_M_storage;
440e4b17023SJohn Marino     };
441e4b17023SJohn Marino 
442e4b17023SJohn Marino   template<_Lock_policy _Lp>
443e4b17023SJohn Marino     class __shared_count
444e4b17023SJohn Marino     {
445e4b17023SJohn Marino     public:
446e4b17023SJohn Marino       constexpr __shared_count() noexcept : _M_pi(0)
447e4b17023SJohn Marino       { }
448e4b17023SJohn Marino 
449e4b17023SJohn Marino       template<typename _Ptr>
450e4b17023SJohn Marino         explicit
451e4b17023SJohn Marino 	__shared_count(_Ptr __p) : _M_pi(0)
452e4b17023SJohn Marino 	{
453e4b17023SJohn Marino 	  __try
454e4b17023SJohn Marino 	    {
455e4b17023SJohn Marino 	      _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);
456e4b17023SJohn Marino 	    }
457e4b17023SJohn Marino 	  __catch(...)
458e4b17023SJohn Marino 	    {
459e4b17023SJohn Marino 	      delete __p;
460e4b17023SJohn Marino 	      __throw_exception_again;
461e4b17023SJohn Marino 	    }
462e4b17023SJohn Marino 	}
463e4b17023SJohn Marino 
464e4b17023SJohn Marino       template<typename _Ptr, typename _Deleter>
465e4b17023SJohn Marino 	__shared_count(_Ptr __p, _Deleter __d) : _M_pi(0)
466e4b17023SJohn Marino 	{
467e4b17023SJohn Marino 	  // The allocator's value_type doesn't matter, will rebind it anyway.
468e4b17023SJohn Marino 	  typedef std::allocator<int> _Alloc;
469e4b17023SJohn Marino 	  typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
470e4b17023SJohn Marino 	  typedef typename allocator_traits<_Alloc>::template
471e4b17023SJohn Marino 	    rebind_traits<_Sp_cd_type> _Alloc_traits;
472e4b17023SJohn Marino 	  typename _Alloc_traits::allocator_type __a;
473e4b17023SJohn Marino 	  _Sp_cd_type* __mem = 0;
474e4b17023SJohn Marino 	  __try
475e4b17023SJohn Marino 	    {
476e4b17023SJohn Marino 	      __mem = _Alloc_traits::allocate(__a, 1);
477e4b17023SJohn Marino 	      _Alloc_traits::construct(__a, __mem, __p, std::move(__d));
478e4b17023SJohn Marino 	      _M_pi = __mem;
479e4b17023SJohn Marino 	    }
480e4b17023SJohn Marino 	  __catch(...)
481e4b17023SJohn Marino 	    {
482e4b17023SJohn Marino 	      __d(__p); // Call _Deleter on __p.
483e4b17023SJohn Marino 	      if (__mem)
484e4b17023SJohn Marino 	        _Alloc_traits::deallocate(__a, __mem, 1);
485e4b17023SJohn Marino 	      __throw_exception_again;
486e4b17023SJohn Marino 	    }
487e4b17023SJohn Marino 	}
488e4b17023SJohn Marino 
489e4b17023SJohn Marino       template<typename _Ptr, typename _Deleter, typename _Alloc>
490e4b17023SJohn Marino 	__shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
491e4b17023SJohn Marino 	{
492e4b17023SJohn Marino 	  typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
493e4b17023SJohn Marino 	  typedef typename allocator_traits<_Alloc>::template
494e4b17023SJohn Marino 	    rebind_traits<_Sp_cd_type> _Alloc_traits;
495e4b17023SJohn Marino 	  typename _Alloc_traits::allocator_type __a2(__a);
496e4b17023SJohn Marino 	  _Sp_cd_type* __mem = 0;
497e4b17023SJohn Marino 	  __try
498e4b17023SJohn Marino 	    {
499e4b17023SJohn Marino 	      __mem = _Alloc_traits::allocate(__a2, 1);
500e4b17023SJohn Marino 	      _Alloc_traits::construct(__a2, __mem,
501e4b17023SJohn Marino 		  __p, std::move(__d), std::move(__a));
502e4b17023SJohn Marino 	      _M_pi = __mem;
503e4b17023SJohn Marino 	    }
504e4b17023SJohn Marino 	  __catch(...)
505e4b17023SJohn Marino 	    {
506e4b17023SJohn Marino 	      __d(__p); // Call _Deleter on __p.
507e4b17023SJohn Marino 	      if (__mem)
508e4b17023SJohn Marino 	        _Alloc_traits::deallocate(__a2, __mem, 1);
509e4b17023SJohn Marino 	      __throw_exception_again;
510e4b17023SJohn Marino 	    }
511e4b17023SJohn Marino 	}
512e4b17023SJohn Marino 
513e4b17023SJohn Marino       template<typename _Tp, typename _Alloc, typename... _Args>
514e4b17023SJohn Marino 	__shared_count(_Sp_make_shared_tag, _Tp*, const _Alloc& __a,
515e4b17023SJohn Marino 		       _Args&&... __args)
516e4b17023SJohn Marino 	: _M_pi(0)
517e4b17023SJohn Marino 	{
518e4b17023SJohn Marino 	  typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;
519e4b17023SJohn Marino 	  typedef typename allocator_traits<_Alloc>::template
520e4b17023SJohn Marino 	    rebind_traits<_Sp_cp_type> _Alloc_traits;
521e4b17023SJohn Marino 	  typename _Alloc_traits::allocator_type __a2(__a);
522e4b17023SJohn Marino 	  _Sp_cp_type* __mem = _Alloc_traits::allocate(__a2, 1);
523e4b17023SJohn Marino 	  __try
524e4b17023SJohn Marino 	    {
525e4b17023SJohn Marino 	      _Alloc_traits::construct(__a2, __mem, std::move(__a),
526e4b17023SJohn Marino 		    std::forward<_Args>(__args)...);
527e4b17023SJohn Marino 	      _M_pi = __mem;
528e4b17023SJohn Marino 	    }
529e4b17023SJohn Marino 	  __catch(...)
530e4b17023SJohn Marino 	    {
531e4b17023SJohn Marino 	      _Alloc_traits::deallocate(__a2, __mem, 1);
532e4b17023SJohn Marino 	      __throw_exception_again;
533e4b17023SJohn Marino 	    }
534e4b17023SJohn Marino 	}
535e4b17023SJohn Marino 
536e4b17023SJohn Marino #if _GLIBCXX_USE_DEPRECATED
537e4b17023SJohn Marino       // Special case for auto_ptr<_Tp> to provide the strong guarantee.
538e4b17023SJohn Marino       template<typename _Tp>
539e4b17023SJohn Marino         explicit
540e4b17023SJohn Marino 	__shared_count(std::auto_ptr<_Tp>&& __r)
541e4b17023SJohn Marino 	: _M_pi(new _Sp_counted_ptr<_Tp*, _Lp>(__r.get()))
542e4b17023SJohn Marino 	{ __r.release(); }
543e4b17023SJohn Marino #endif
544e4b17023SJohn Marino 
545e4b17023SJohn Marino       // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee.
546e4b17023SJohn Marino       template<typename _Tp, typename _Del>
547e4b17023SJohn Marino         explicit
548e4b17023SJohn Marino 	__shared_count(std::unique_ptr<_Tp, _Del>&& __r)
549e4b17023SJohn Marino 	: _M_pi(_S_create_from_up(std::move(__r)))
550e4b17023SJohn Marino 	{ __r.release(); }
551e4b17023SJohn Marino 
552e4b17023SJohn Marino       // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
553e4b17023SJohn Marino       explicit __shared_count(const __weak_count<_Lp>& __r);
554e4b17023SJohn Marino 
555e4b17023SJohn Marino       ~__shared_count() noexcept
556e4b17023SJohn Marino       {
557e4b17023SJohn Marino 	if (_M_pi != 0)
558e4b17023SJohn Marino 	  _M_pi->_M_release();
559e4b17023SJohn Marino       }
560e4b17023SJohn Marino 
561e4b17023SJohn Marino       __shared_count(const __shared_count& __r) noexcept
562e4b17023SJohn Marino       : _M_pi(__r._M_pi)
563e4b17023SJohn Marino       {
564e4b17023SJohn Marino 	if (_M_pi != 0)
565e4b17023SJohn Marino 	  _M_pi->_M_add_ref_copy();
566e4b17023SJohn Marino       }
567e4b17023SJohn Marino 
568e4b17023SJohn Marino       __shared_count&
569e4b17023SJohn Marino       operator=(const __shared_count& __r) noexcept
570e4b17023SJohn Marino       {
571e4b17023SJohn Marino 	_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
572e4b17023SJohn Marino 	if (__tmp != _M_pi)
573e4b17023SJohn Marino 	  {
574e4b17023SJohn Marino 	    if (__tmp != 0)
575e4b17023SJohn Marino 	      __tmp->_M_add_ref_copy();
576e4b17023SJohn Marino 	    if (_M_pi != 0)
577e4b17023SJohn Marino 	      _M_pi->_M_release();
578e4b17023SJohn Marino 	    _M_pi = __tmp;
579e4b17023SJohn Marino 	  }
580e4b17023SJohn Marino 	return *this;
581e4b17023SJohn Marino       }
582e4b17023SJohn Marino 
583e4b17023SJohn Marino       void
584e4b17023SJohn Marino       _M_swap(__shared_count& __r) noexcept
585e4b17023SJohn Marino       {
586e4b17023SJohn Marino 	_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
587e4b17023SJohn Marino 	__r._M_pi = _M_pi;
588e4b17023SJohn Marino 	_M_pi = __tmp;
589e4b17023SJohn Marino       }
590e4b17023SJohn Marino 
591e4b17023SJohn Marino       long
592e4b17023SJohn Marino       _M_get_use_count() const noexcept
593e4b17023SJohn Marino       { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
594e4b17023SJohn Marino 
595e4b17023SJohn Marino       bool
596e4b17023SJohn Marino       _M_unique() const noexcept
597e4b17023SJohn Marino       { return this->_M_get_use_count() == 1; }
598e4b17023SJohn Marino 
599e4b17023SJohn Marino       void*
600e4b17023SJohn Marino       _M_get_deleter(const std::type_info& __ti) const noexcept
601e4b17023SJohn Marino       { return _M_pi ? _M_pi->_M_get_deleter(__ti) : 0; }
602e4b17023SJohn Marino 
603e4b17023SJohn Marino       bool
604e4b17023SJohn Marino       _M_less(const __shared_count& __rhs) const noexcept
605e4b17023SJohn Marino       { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
606e4b17023SJohn Marino 
607e4b17023SJohn Marino       bool
608e4b17023SJohn Marino       _M_less(const __weak_count<_Lp>& __rhs) const noexcept
609e4b17023SJohn Marino       { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
610e4b17023SJohn Marino 
611e4b17023SJohn Marino       // Friend function injected into enclosing namespace and found by ADL
612e4b17023SJohn Marino       friend inline bool
613e4b17023SJohn Marino       operator==(const __shared_count& __a, const __shared_count& __b) noexcept
614e4b17023SJohn Marino       { return __a._M_pi == __b._M_pi; }
615e4b17023SJohn Marino 
616e4b17023SJohn Marino     private:
617e4b17023SJohn Marino       friend class __weak_count<_Lp>;
618e4b17023SJohn Marino 
619e4b17023SJohn Marino       template<typename _Tp, typename _Del>
620e4b17023SJohn Marino 	static _Sp_counted_base<_Lp>*
621e4b17023SJohn Marino 	_S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r,
622e4b17023SJohn Marino 	  typename std::enable_if<!std::is_reference<_Del>::value>::type* = 0)
623e4b17023SJohn Marino 	{
6245ce9237cSJohn Marino 	  return new _Sp_counted_deleter<_Tp*, _Del, std::allocator<void>,
625e4b17023SJohn Marino 	    _Lp>(__r.get(), __r.get_deleter());
626e4b17023SJohn Marino 	}
627e4b17023SJohn Marino 
628e4b17023SJohn Marino       template<typename _Tp, typename _Del>
629e4b17023SJohn Marino 	static _Sp_counted_base<_Lp>*
630e4b17023SJohn Marino 	_S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r,
631e4b17023SJohn Marino 	  typename std::enable_if<std::is_reference<_Del>::value>::type* = 0)
632e4b17023SJohn Marino 	{
633e4b17023SJohn Marino 	  typedef typename std::remove_reference<_Del>::type _Del1;
634e4b17023SJohn Marino 	  typedef std::reference_wrapper<_Del1> _Del2;
6355ce9237cSJohn Marino 	  return new _Sp_counted_deleter<_Tp*, _Del2, std::allocator<void>,
636e4b17023SJohn Marino 	    _Lp>(__r.get(), std::ref(__r.get_deleter()));
637e4b17023SJohn Marino 	}
638e4b17023SJohn Marino 
639e4b17023SJohn Marino       _Sp_counted_base<_Lp>*  _M_pi;
640e4b17023SJohn Marino     };
641e4b17023SJohn Marino 
642e4b17023SJohn Marino 
643e4b17023SJohn Marino   template<_Lock_policy _Lp>
644e4b17023SJohn Marino     class __weak_count
645e4b17023SJohn Marino     {
646e4b17023SJohn Marino     public:
647e4b17023SJohn Marino       constexpr __weak_count() noexcept : _M_pi(0)
648e4b17023SJohn Marino       { }
649e4b17023SJohn Marino 
650e4b17023SJohn Marino       __weak_count(const __shared_count<_Lp>& __r) noexcept
651e4b17023SJohn Marino       : _M_pi(__r._M_pi)
652e4b17023SJohn Marino       {
653e4b17023SJohn Marino 	if (_M_pi != 0)
654e4b17023SJohn Marino 	  _M_pi->_M_weak_add_ref();
655e4b17023SJohn Marino       }
656e4b17023SJohn Marino 
657e4b17023SJohn Marino       __weak_count(const __weak_count<_Lp>& __r) noexcept
658e4b17023SJohn Marino       : _M_pi(__r._M_pi)
659e4b17023SJohn Marino       {
660e4b17023SJohn Marino 	if (_M_pi != 0)
661e4b17023SJohn Marino 	  _M_pi->_M_weak_add_ref();
662e4b17023SJohn Marino       }
663e4b17023SJohn Marino 
664e4b17023SJohn Marino       ~__weak_count() noexcept
665e4b17023SJohn Marino       {
666e4b17023SJohn Marino 	if (_M_pi != 0)
667e4b17023SJohn Marino 	  _M_pi->_M_weak_release();
668e4b17023SJohn Marino       }
669e4b17023SJohn Marino 
670e4b17023SJohn Marino       __weak_count<_Lp>&
671e4b17023SJohn Marino       operator=(const __shared_count<_Lp>& __r) noexcept
672e4b17023SJohn Marino       {
673e4b17023SJohn Marino 	_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
674e4b17023SJohn Marino 	if (__tmp != 0)
675e4b17023SJohn Marino 	  __tmp->_M_weak_add_ref();
676e4b17023SJohn Marino 	if (_M_pi != 0)
677e4b17023SJohn Marino 	  _M_pi->_M_weak_release();
678e4b17023SJohn Marino 	_M_pi = __tmp;
679e4b17023SJohn Marino 	return *this;
680e4b17023SJohn Marino       }
681e4b17023SJohn Marino 
682e4b17023SJohn Marino       __weak_count<_Lp>&
683e4b17023SJohn Marino       operator=(const __weak_count<_Lp>& __r) noexcept
684e4b17023SJohn Marino       {
685e4b17023SJohn Marino 	_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
686e4b17023SJohn Marino 	if (__tmp != 0)
687e4b17023SJohn Marino 	  __tmp->_M_weak_add_ref();
688e4b17023SJohn Marino 	if (_M_pi != 0)
689e4b17023SJohn Marino 	  _M_pi->_M_weak_release();
690e4b17023SJohn Marino 	_M_pi = __tmp;
691e4b17023SJohn Marino 	return *this;
692e4b17023SJohn Marino       }
693e4b17023SJohn Marino 
694e4b17023SJohn Marino       void
695e4b17023SJohn Marino       _M_swap(__weak_count<_Lp>& __r) noexcept
696e4b17023SJohn Marino       {
697e4b17023SJohn Marino 	_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
698e4b17023SJohn Marino 	__r._M_pi = _M_pi;
699e4b17023SJohn Marino 	_M_pi = __tmp;
700e4b17023SJohn Marino       }
701e4b17023SJohn Marino 
702e4b17023SJohn Marino       long
703e4b17023SJohn Marino       _M_get_use_count() const noexcept
704e4b17023SJohn Marino       { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
705e4b17023SJohn Marino 
706e4b17023SJohn Marino       bool
707e4b17023SJohn Marino       _M_less(const __weak_count& __rhs) const noexcept
708e4b17023SJohn Marino       { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
709e4b17023SJohn Marino 
710e4b17023SJohn Marino       bool
711e4b17023SJohn Marino       _M_less(const __shared_count<_Lp>& __rhs) const noexcept
712e4b17023SJohn Marino       { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
713e4b17023SJohn Marino 
714e4b17023SJohn Marino       // Friend function injected into enclosing namespace and found by ADL
715e4b17023SJohn Marino       friend inline bool
716e4b17023SJohn Marino       operator==(const __weak_count& __a, const __weak_count& __b) noexcept
717e4b17023SJohn Marino       { return __a._M_pi == __b._M_pi; }
718e4b17023SJohn Marino 
719e4b17023SJohn Marino     private:
720e4b17023SJohn Marino       friend class __shared_count<_Lp>;
721e4b17023SJohn Marino 
722e4b17023SJohn Marino       _Sp_counted_base<_Lp>*  _M_pi;
723e4b17023SJohn Marino     };
724e4b17023SJohn Marino 
725e4b17023SJohn Marino   // Now that __weak_count is defined we can define this constructor:
726e4b17023SJohn Marino   template<_Lock_policy _Lp>
727e4b17023SJohn Marino     inline __shared_count<_Lp>:: __shared_count(const __weak_count<_Lp>& __r)
728e4b17023SJohn Marino     : _M_pi(__r._M_pi)
729e4b17023SJohn Marino     {
730e4b17023SJohn Marino       if (_M_pi != 0)
731e4b17023SJohn Marino 	_M_pi->_M_add_ref_lock();
732e4b17023SJohn Marino       else
733e4b17023SJohn Marino 	__throw_bad_weak_ptr();
734e4b17023SJohn Marino     }
735e4b17023SJohn Marino 
736e4b17023SJohn Marino 
737e4b17023SJohn Marino   // Support for enable_shared_from_this.
738e4b17023SJohn Marino 
739e4b17023SJohn Marino   // Friend of __enable_shared_from_this.
740e4b17023SJohn Marino   template<_Lock_policy _Lp, typename _Tp1, typename _Tp2>
741e4b17023SJohn Marino     void
742e4b17023SJohn Marino     __enable_shared_from_this_helper(const __shared_count<_Lp>&,
743e4b17023SJohn Marino 				     const __enable_shared_from_this<_Tp1,
744e4b17023SJohn Marino 				     _Lp>*, const _Tp2*) noexcept;
745e4b17023SJohn Marino 
746e4b17023SJohn Marino   // Friend of enable_shared_from_this.
747e4b17023SJohn Marino   template<typename _Tp1, typename _Tp2>
748e4b17023SJohn Marino     void
749e4b17023SJohn Marino     __enable_shared_from_this_helper(const __shared_count<>&,
750e4b17023SJohn Marino 				     const enable_shared_from_this<_Tp1>*,
751e4b17023SJohn Marino 				     const _Tp2*) noexcept;
752e4b17023SJohn Marino 
753e4b17023SJohn Marino   template<_Lock_policy _Lp>
754e4b17023SJohn Marino     inline void
755e4b17023SJohn Marino     __enable_shared_from_this_helper(const __shared_count<_Lp>&, ...) noexcept
756e4b17023SJohn Marino     { }
757e4b17023SJohn Marino 
758e4b17023SJohn Marino 
759e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
760e4b17023SJohn Marino     class __shared_ptr
761e4b17023SJohn Marino     {
762e4b17023SJohn Marino     public:
763e4b17023SJohn Marino       typedef _Tp   element_type;
764e4b17023SJohn Marino 
765e4b17023SJohn Marino       constexpr __shared_ptr() noexcept
766e4b17023SJohn Marino       : _M_ptr(0), _M_refcount()
767e4b17023SJohn Marino       { }
768e4b17023SJohn Marino 
769e4b17023SJohn Marino       template<typename _Tp1>
770e4b17023SJohn Marino 	explicit __shared_ptr(_Tp1* __p)
771e4b17023SJohn Marino         : _M_ptr(__p), _M_refcount(__p)
772e4b17023SJohn Marino 	{
773e4b17023SJohn Marino 	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
774e4b17023SJohn Marino 	  static_assert( sizeof(_Tp1) > 0, "incomplete type" );
775e4b17023SJohn Marino 	  __enable_shared_from_this_helper(_M_refcount, __p, __p);
776e4b17023SJohn Marino 	}
777e4b17023SJohn Marino 
778e4b17023SJohn Marino       template<typename _Tp1, typename _Deleter>
779e4b17023SJohn Marino 	__shared_ptr(_Tp1* __p, _Deleter __d)
780e4b17023SJohn Marino 	: _M_ptr(__p), _M_refcount(__p, __d)
781e4b17023SJohn Marino 	{
782e4b17023SJohn Marino 	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
783e4b17023SJohn Marino 	  // TODO requires _Deleter CopyConstructible and __d(__p) well-formed
784e4b17023SJohn Marino 	  __enable_shared_from_this_helper(_M_refcount, __p, __p);
785e4b17023SJohn Marino 	}
786e4b17023SJohn Marino 
787e4b17023SJohn Marino       template<typename _Tp1, typename _Deleter, typename _Alloc>
788e4b17023SJohn Marino 	__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
789e4b17023SJohn Marino 	: _M_ptr(__p), _M_refcount(__p, __d, std::move(__a))
790e4b17023SJohn Marino 	{
791e4b17023SJohn Marino 	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
792e4b17023SJohn Marino 	  // TODO requires _Deleter CopyConstructible and __d(__p) well-formed
793e4b17023SJohn Marino 	  __enable_shared_from_this_helper(_M_refcount, __p, __p);
794e4b17023SJohn Marino 	}
795e4b17023SJohn Marino 
796e4b17023SJohn Marino       template<typename _Deleter>
797e4b17023SJohn Marino 	__shared_ptr(nullptr_t __p, _Deleter __d)
798e4b17023SJohn Marino 	: _M_ptr(0), _M_refcount(__p, __d)
799e4b17023SJohn Marino 	{ }
800e4b17023SJohn Marino 
801e4b17023SJohn Marino       template<typename _Deleter, typename _Alloc>
802e4b17023SJohn Marino         __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
803e4b17023SJohn Marino 	: _M_ptr(0), _M_refcount(__p, __d, std::move(__a))
804e4b17023SJohn Marino 	{ }
805e4b17023SJohn Marino 
806e4b17023SJohn Marino       template<typename _Tp1>
807e4b17023SJohn Marino 	__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) noexcept
808e4b17023SJohn Marino 	: _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
809e4b17023SJohn Marino 	{ }
810e4b17023SJohn Marino 
811e4b17023SJohn Marino       __shared_ptr(const __shared_ptr&) noexcept = default;
812e4b17023SJohn Marino       __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
813e4b17023SJohn Marino       ~__shared_ptr() = default;
814e4b17023SJohn Marino 
815e4b17023SJohn Marino       template<typename _Tp1, typename = typename
816e4b17023SJohn Marino 	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
817e4b17023SJohn Marino 	__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
818e4b17023SJohn Marino 	: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
819e4b17023SJohn Marino 	{ }
820e4b17023SJohn Marino 
821e4b17023SJohn Marino       __shared_ptr(__shared_ptr&& __r) noexcept
822e4b17023SJohn Marino       : _M_ptr(__r._M_ptr), _M_refcount()
823e4b17023SJohn Marino       {
824e4b17023SJohn Marino 	_M_refcount._M_swap(__r._M_refcount);
825e4b17023SJohn Marino 	__r._M_ptr = 0;
826e4b17023SJohn Marino       }
827e4b17023SJohn Marino 
828e4b17023SJohn Marino       template<typename _Tp1, typename = typename
829e4b17023SJohn Marino 	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
830e4b17023SJohn Marino 	__shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
831e4b17023SJohn Marino 	: _M_ptr(__r._M_ptr), _M_refcount()
832e4b17023SJohn Marino 	{
833e4b17023SJohn Marino 	  _M_refcount._M_swap(__r._M_refcount);
834e4b17023SJohn Marino 	  __r._M_ptr = 0;
835e4b17023SJohn Marino 	}
836e4b17023SJohn Marino 
837e4b17023SJohn Marino       template<typename _Tp1>
838e4b17023SJohn Marino 	explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
839e4b17023SJohn Marino 	: _M_refcount(__r._M_refcount) // may throw
840e4b17023SJohn Marino 	{
841e4b17023SJohn Marino 	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
842e4b17023SJohn Marino 
843e4b17023SJohn Marino 	  // It is now safe to copy __r._M_ptr, as
844e4b17023SJohn Marino 	  // _M_refcount(__r._M_refcount) did not throw.
845e4b17023SJohn Marino 	  _M_ptr = __r._M_ptr;
846e4b17023SJohn Marino 	}
847e4b17023SJohn Marino 
848e4b17023SJohn Marino       // If an exception is thrown this constructor has no effect.
849e4b17023SJohn Marino       template<typename _Tp1, typename _Del>
850e4b17023SJohn Marino 	__shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
851e4b17023SJohn Marino 	: _M_ptr(__r.get()), _M_refcount()
852e4b17023SJohn Marino 	{
853e4b17023SJohn Marino 	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
854e4b17023SJohn Marino 	  _Tp1* __tmp = __r.get();
855e4b17023SJohn Marino 	  _M_refcount = __shared_count<_Lp>(std::move(__r));
856e4b17023SJohn Marino 	  __enable_shared_from_this_helper(_M_refcount, __tmp, __tmp);
857e4b17023SJohn Marino 	}
858e4b17023SJohn Marino 
859e4b17023SJohn Marino #if _GLIBCXX_USE_DEPRECATED
860e4b17023SJohn Marino       // Postcondition: use_count() == 1 and __r.get() == 0
861e4b17023SJohn Marino       template<typename _Tp1>
862e4b17023SJohn Marino 	__shared_ptr(std::auto_ptr<_Tp1>&& __r)
863e4b17023SJohn Marino 	: _M_ptr(__r.get()), _M_refcount()
864e4b17023SJohn Marino 	{
865e4b17023SJohn Marino 	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
866e4b17023SJohn Marino 	  static_assert( sizeof(_Tp1) > 0, "incomplete type" );
867e4b17023SJohn Marino 	  _Tp1* __tmp = __r.get();
868e4b17023SJohn Marino 	  _M_refcount = __shared_count<_Lp>(std::move(__r));
869e4b17023SJohn Marino 	  __enable_shared_from_this_helper(_M_refcount, __tmp, __tmp);
870e4b17023SJohn Marino 	}
871e4b17023SJohn Marino #endif
872e4b17023SJohn Marino 
873e4b17023SJohn Marino       /* TODO: use delegating constructor */
874e4b17023SJohn Marino       constexpr __shared_ptr(nullptr_t) noexcept
875e4b17023SJohn Marino       : _M_ptr(0), _M_refcount()
876e4b17023SJohn Marino       { }
877e4b17023SJohn Marino 
878e4b17023SJohn Marino       template<typename _Tp1>
879e4b17023SJohn Marino 	__shared_ptr&
880e4b17023SJohn Marino 	operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
881e4b17023SJohn Marino 	{
882e4b17023SJohn Marino 	  _M_ptr = __r._M_ptr;
883e4b17023SJohn Marino 	  _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
884e4b17023SJohn Marino 	  return *this;
885e4b17023SJohn Marino 	}
886e4b17023SJohn Marino 
887e4b17023SJohn Marino #if _GLIBCXX_USE_DEPRECATED
888e4b17023SJohn Marino       template<typename _Tp1>
889e4b17023SJohn Marino 	__shared_ptr&
890e4b17023SJohn Marino 	operator=(std::auto_ptr<_Tp1>&& __r)
891e4b17023SJohn Marino 	{
892e4b17023SJohn Marino 	  __shared_ptr(std::move(__r)).swap(*this);
893e4b17023SJohn Marino 	  return *this;
894e4b17023SJohn Marino 	}
895e4b17023SJohn Marino #endif
896e4b17023SJohn Marino 
897e4b17023SJohn Marino       __shared_ptr&
898e4b17023SJohn Marino       operator=(__shared_ptr&& __r) noexcept
899e4b17023SJohn Marino       {
900e4b17023SJohn Marino 	__shared_ptr(std::move(__r)).swap(*this);
901e4b17023SJohn Marino 	return *this;
902e4b17023SJohn Marino       }
903e4b17023SJohn Marino 
904e4b17023SJohn Marino       template<class _Tp1>
905e4b17023SJohn Marino 	__shared_ptr&
906e4b17023SJohn Marino 	operator=(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
907e4b17023SJohn Marino 	{
908e4b17023SJohn Marino 	  __shared_ptr(std::move(__r)).swap(*this);
909e4b17023SJohn Marino 	  return *this;
910e4b17023SJohn Marino 	}
911e4b17023SJohn Marino 
912e4b17023SJohn Marino       template<typename _Tp1, typename _Del>
913e4b17023SJohn Marino 	__shared_ptr&
914e4b17023SJohn Marino 	operator=(std::unique_ptr<_Tp1, _Del>&& __r)
915e4b17023SJohn Marino 	{
916e4b17023SJohn Marino 	  __shared_ptr(std::move(__r)).swap(*this);
917e4b17023SJohn Marino 	  return *this;
918e4b17023SJohn Marino 	}
919e4b17023SJohn Marino 
920e4b17023SJohn Marino       void
921e4b17023SJohn Marino       reset() noexcept
922e4b17023SJohn Marino       { __shared_ptr().swap(*this); }
923e4b17023SJohn Marino 
924e4b17023SJohn Marino       template<typename _Tp1>
925e4b17023SJohn Marino 	void
926e4b17023SJohn Marino 	reset(_Tp1* __p) // _Tp1 must be complete.
927e4b17023SJohn Marino 	{
928e4b17023SJohn Marino 	  // Catch self-reset errors.
929e4b17023SJohn Marino 	  _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr);
930e4b17023SJohn Marino 	  __shared_ptr(__p).swap(*this);
931e4b17023SJohn Marino 	}
932e4b17023SJohn Marino 
933e4b17023SJohn Marino       template<typename _Tp1, typename _Deleter>
934e4b17023SJohn Marino 	void
935e4b17023SJohn Marino 	reset(_Tp1* __p, _Deleter __d)
936e4b17023SJohn Marino 	{ __shared_ptr(__p, __d).swap(*this); }
937e4b17023SJohn Marino 
938e4b17023SJohn Marino       template<typename _Tp1, typename _Deleter, typename _Alloc>
939e4b17023SJohn Marino 	void
940e4b17023SJohn Marino         reset(_Tp1* __p, _Deleter __d, _Alloc __a)
941e4b17023SJohn Marino         { __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
942e4b17023SJohn Marino 
943e4b17023SJohn Marino       // Allow class instantiation when _Tp is [cv-qual] void.
944e4b17023SJohn Marino       typename std::add_lvalue_reference<_Tp>::type
945e4b17023SJohn Marino       operator*() const noexcept
946e4b17023SJohn Marino       {
947e4b17023SJohn Marino 	_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
948e4b17023SJohn Marino 	return *_M_ptr;
949e4b17023SJohn Marino       }
950e4b17023SJohn Marino 
951e4b17023SJohn Marino       _Tp*
952e4b17023SJohn Marino       operator->() const noexcept
953e4b17023SJohn Marino       {
954e4b17023SJohn Marino 	_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
955e4b17023SJohn Marino 	return _M_ptr;
956e4b17023SJohn Marino       }
957e4b17023SJohn Marino 
958e4b17023SJohn Marino       _Tp*
959e4b17023SJohn Marino       get() const noexcept
960e4b17023SJohn Marino       { return _M_ptr; }
961e4b17023SJohn Marino 
962e4b17023SJohn Marino       explicit operator bool() const // never throws
963e4b17023SJohn Marino       { return _M_ptr == 0 ? false : true; }
964e4b17023SJohn Marino 
965e4b17023SJohn Marino       bool
966e4b17023SJohn Marino       unique() const noexcept
967e4b17023SJohn Marino       { return _M_refcount._M_unique(); }
968e4b17023SJohn Marino 
969e4b17023SJohn Marino       long
970e4b17023SJohn Marino       use_count() const noexcept
971e4b17023SJohn Marino       { return _M_refcount._M_get_use_count(); }
972e4b17023SJohn Marino 
973e4b17023SJohn Marino       void
974e4b17023SJohn Marino       swap(__shared_ptr<_Tp, _Lp>& __other) noexcept
975e4b17023SJohn Marino       {
976e4b17023SJohn Marino 	std::swap(_M_ptr, __other._M_ptr);
977e4b17023SJohn Marino 	_M_refcount._M_swap(__other._M_refcount);
978e4b17023SJohn Marino       }
979e4b17023SJohn Marino 
980e4b17023SJohn Marino       template<typename _Tp1>
981e4b17023SJohn Marino 	bool
982e4b17023SJohn Marino 	owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const
983e4b17023SJohn Marino 	{ return _M_refcount._M_less(__rhs._M_refcount); }
984e4b17023SJohn Marino 
985e4b17023SJohn Marino       template<typename _Tp1>
986e4b17023SJohn Marino 	bool
987e4b17023SJohn Marino 	owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const
988e4b17023SJohn Marino 	{ return _M_refcount._M_less(__rhs._M_refcount); }
989e4b17023SJohn Marino 
990e4b17023SJohn Marino #ifdef __GXX_RTTI
991e4b17023SJohn Marino     protected:
992e4b17023SJohn Marino       // This constructor is non-standard, it is used by allocate_shared.
993e4b17023SJohn Marino       template<typename _Alloc, typename... _Args>
994e4b17023SJohn Marino 	__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
995e4b17023SJohn Marino 		     _Args&&... __args)
996e4b17023SJohn Marino 	: _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
997e4b17023SJohn Marino 				std::forward<_Args>(__args)...)
998e4b17023SJohn Marino 	{
999e4b17023SJohn Marino 	  // _M_ptr needs to point to the newly constructed object.
1000e4b17023SJohn Marino 	  // This relies on _Sp_counted_ptr_inplace::_M_get_deleter.
1001e4b17023SJohn Marino 	  void* __p = _M_refcount._M_get_deleter(typeid(__tag));
1002e4b17023SJohn Marino 	  _M_ptr = static_cast<_Tp*>(__p);
1003e4b17023SJohn Marino 	  __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
1004e4b17023SJohn Marino 	}
1005e4b17023SJohn Marino #else
1006e4b17023SJohn Marino       template<typename _Alloc>
1007e4b17023SJohn Marino         struct _Deleter
1008e4b17023SJohn Marino         {
1009e4b17023SJohn Marino           void operator()(_Tp* __ptr)
1010e4b17023SJohn Marino           {
1011e4b17023SJohn Marino 	    typedef allocator_traits<_Alloc> _Alloc_traits;
1012e4b17023SJohn Marino 	    _Alloc_traits::destroy(_M_alloc, __ptr);
1013e4b17023SJohn Marino 	    _Alloc_traits::deallocate(_M_alloc, __ptr, 1);
1014e4b17023SJohn Marino           }
1015e4b17023SJohn Marino           _Alloc _M_alloc;
1016e4b17023SJohn Marino         };
1017e4b17023SJohn Marino 
1018e4b17023SJohn Marino       template<typename _Alloc, typename... _Args>
1019e4b17023SJohn Marino 	__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
1020e4b17023SJohn Marino 		     _Args&&... __args)
1021e4b17023SJohn Marino 	: _M_ptr(), _M_refcount()
1022e4b17023SJohn Marino         {
1023e4b17023SJohn Marino 	  typedef typename _Alloc::template rebind<_Tp>::other _Alloc2;
1024e4b17023SJohn Marino           _Deleter<_Alloc2> __del = { _Alloc2(__a) };
1025e4b17023SJohn Marino 	  typedef allocator_traits<_Alloc2> __traits;
1026e4b17023SJohn Marino           _M_ptr = __traits::allocate(__del._M_alloc, 1);
1027e4b17023SJohn Marino 	  __try
1028e4b17023SJohn Marino 	    {
1029e4b17023SJohn Marino 	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
1030e4b17023SJohn Marino 	      // 2070. allocate_shared should use allocator_traits<A>::construct
1031e4b17023SJohn Marino 	      __traits::construct(__del._M_alloc, _M_ptr,
1032e4b17023SJohn Marino 		                  std::forward<_Args>(__args)...);
1033e4b17023SJohn Marino 	    }
1034e4b17023SJohn Marino 	  __catch(...)
1035e4b17023SJohn Marino 	    {
1036e4b17023SJohn Marino 	      __traits::deallocate(__del._M_alloc, _M_ptr, 1);
1037e4b17023SJohn Marino 	      __throw_exception_again;
1038e4b17023SJohn Marino 	    }
1039e4b17023SJohn Marino           __shared_count<_Lp> __count(_M_ptr, __del, __del._M_alloc);
1040e4b17023SJohn Marino           _M_refcount._M_swap(__count);
1041e4b17023SJohn Marino 	  __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
1042e4b17023SJohn Marino         }
1043e4b17023SJohn Marino #endif
1044e4b17023SJohn Marino 
1045e4b17023SJohn Marino       template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc,
1046e4b17023SJohn Marino 	       typename... _Args>
1047e4b17023SJohn Marino 	friend __shared_ptr<_Tp1, _Lp1>
1048e4b17023SJohn Marino 	__allocate_shared(const _Alloc& __a, _Args&&... __args);
1049e4b17023SJohn Marino 
1050e4b17023SJohn Marino     private:
1051e4b17023SJohn Marino       void*
1052e4b17023SJohn Marino       _M_get_deleter(const std::type_info& __ti) const noexcept
1053e4b17023SJohn Marino       { return _M_refcount._M_get_deleter(__ti); }
1054e4b17023SJohn Marino 
1055e4b17023SJohn Marino       template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
1056e4b17023SJohn Marino       template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
1057e4b17023SJohn Marino 
1058e4b17023SJohn Marino       template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
1059e4b17023SJohn Marino 	friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
1060e4b17023SJohn Marino 
1061e4b17023SJohn Marino       _Tp*	   	   _M_ptr;         // Contained pointer.
1062e4b17023SJohn Marino       __shared_count<_Lp>  _M_refcount;    // Reference counter.
1063e4b17023SJohn Marino     };
1064e4b17023SJohn Marino 
1065e4b17023SJohn Marino 
1066e4b17023SJohn Marino   // 20.8.13.2.7 shared_ptr comparisons
1067e4b17023SJohn Marino   template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1068e4b17023SJohn Marino     inline bool
1069e4b17023SJohn Marino     operator==(const __shared_ptr<_Tp1, _Lp>& __a,
1070e4b17023SJohn Marino 	       const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1071e4b17023SJohn Marino     { return __a.get() == __b.get(); }
1072e4b17023SJohn Marino 
1073e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1074e4b17023SJohn Marino     inline bool
1075e4b17023SJohn Marino     operator==(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1076e4b17023SJohn Marino     { return !__a; }
1077e4b17023SJohn Marino 
1078e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1079e4b17023SJohn Marino     inline bool
1080e4b17023SJohn Marino     operator==(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1081e4b17023SJohn Marino     { return !__a; }
1082e4b17023SJohn Marino 
1083e4b17023SJohn Marino   template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1084e4b17023SJohn Marino     inline bool
1085e4b17023SJohn Marino     operator!=(const __shared_ptr<_Tp1, _Lp>& __a,
1086e4b17023SJohn Marino 	       const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1087e4b17023SJohn Marino     { return __a.get() != __b.get(); }
1088e4b17023SJohn Marino 
1089e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1090e4b17023SJohn Marino     inline bool
1091e4b17023SJohn Marino     operator!=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1092e4b17023SJohn Marino     { return (bool)__a; }
1093e4b17023SJohn Marino 
1094e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1095e4b17023SJohn Marino     inline bool
1096e4b17023SJohn Marino     operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1097e4b17023SJohn Marino     { return (bool)__a; }
1098e4b17023SJohn Marino 
1099e4b17023SJohn Marino   template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1100e4b17023SJohn Marino     inline bool
1101e4b17023SJohn Marino     operator<(const __shared_ptr<_Tp1, _Lp>& __a,
1102e4b17023SJohn Marino 	      const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1103e4b17023SJohn Marino     {
1104e4b17023SJohn Marino       typedef typename std::common_type<_Tp1*, _Tp2*>::type _CT;
1105e4b17023SJohn Marino       return std::less<_CT>()(__a.get(), __b.get());
1106e4b17023SJohn Marino     }
1107e4b17023SJohn Marino 
1108e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1109e4b17023SJohn Marino     inline bool
1110e4b17023SJohn Marino     operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1111e4b17023SJohn Marino     { return std::less<_Tp*>()(__a.get(), nullptr); }
1112e4b17023SJohn Marino 
1113e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1114e4b17023SJohn Marino     inline bool
1115e4b17023SJohn Marino     operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1116e4b17023SJohn Marino     { return std::less<_Tp*>()(nullptr, __a.get()); }
1117e4b17023SJohn Marino 
1118e4b17023SJohn Marino   template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1119e4b17023SJohn Marino     inline bool
1120e4b17023SJohn Marino     operator<=(const __shared_ptr<_Tp1, _Lp>& __a,
1121e4b17023SJohn Marino 	       const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1122e4b17023SJohn Marino     { return !(__b < __a); }
1123e4b17023SJohn Marino 
1124e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1125e4b17023SJohn Marino     inline bool
1126e4b17023SJohn Marino     operator<=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1127e4b17023SJohn Marino     { return !(nullptr < __a); }
1128e4b17023SJohn Marino 
1129e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1130e4b17023SJohn Marino     inline bool
1131e4b17023SJohn Marino     operator<=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1132e4b17023SJohn Marino     { return !(__a < nullptr); }
1133e4b17023SJohn Marino 
1134e4b17023SJohn Marino   template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1135e4b17023SJohn Marino     inline bool
1136e4b17023SJohn Marino     operator>(const __shared_ptr<_Tp1, _Lp>& __a,
1137e4b17023SJohn Marino 	      const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1138e4b17023SJohn Marino     { return (__b < __a); }
1139e4b17023SJohn Marino 
1140e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1141e4b17023SJohn Marino     inline bool
1142e4b17023SJohn Marino     operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1143e4b17023SJohn Marino     { return std::less<_Tp*>()(nullptr, __a.get()); }
1144e4b17023SJohn Marino 
1145e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1146e4b17023SJohn Marino     inline bool
1147e4b17023SJohn Marino     operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1148e4b17023SJohn Marino     { return std::less<_Tp*>()(__a.get(), nullptr); }
1149e4b17023SJohn Marino 
1150e4b17023SJohn Marino   template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1151e4b17023SJohn Marino     inline bool
1152e4b17023SJohn Marino     operator>=(const __shared_ptr<_Tp1, _Lp>& __a,
1153e4b17023SJohn Marino 	       const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1154e4b17023SJohn Marino     { return !(__a < __b); }
1155e4b17023SJohn Marino 
1156e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1157e4b17023SJohn Marino     inline bool
1158e4b17023SJohn Marino     operator>=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1159e4b17023SJohn Marino     { return !(__a < nullptr); }
1160e4b17023SJohn Marino 
1161e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1162e4b17023SJohn Marino     inline bool
1163e4b17023SJohn Marino     operator>=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1164e4b17023SJohn Marino     { return !(nullptr < __a); }
1165e4b17023SJohn Marino 
1166e4b17023SJohn Marino   template<typename _Sp>
1167e4b17023SJohn Marino     struct _Sp_less : public binary_function<_Sp, _Sp, bool>
1168e4b17023SJohn Marino     {
1169e4b17023SJohn Marino       bool
1170e4b17023SJohn Marino       operator()(const _Sp& __lhs, const _Sp& __rhs) const noexcept
1171e4b17023SJohn Marino       {
1172e4b17023SJohn Marino 	typedef typename _Sp::element_type element_type;
1173e4b17023SJohn Marino 	return std::less<element_type*>()(__lhs.get(), __rhs.get());
1174e4b17023SJohn Marino       }
1175e4b17023SJohn Marino     };
1176e4b17023SJohn Marino 
1177e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1178e4b17023SJohn Marino     struct less<__shared_ptr<_Tp, _Lp>>
1179e4b17023SJohn Marino     : public _Sp_less<__shared_ptr<_Tp, _Lp>>
1180e4b17023SJohn Marino     { };
1181e4b17023SJohn Marino 
1182e4b17023SJohn Marino   // 2.2.3.8 shared_ptr specialized algorithms.
1183e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1184e4b17023SJohn Marino     inline void
1185e4b17023SJohn Marino     swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) noexcept
1186e4b17023SJohn Marino     { __a.swap(__b); }
1187e4b17023SJohn Marino 
1188e4b17023SJohn Marino   // 2.2.3.9 shared_ptr casts
1189e4b17023SJohn Marino 
1190e4b17023SJohn Marino   // The seemingly equivalent code:
1191e4b17023SJohn Marino   // shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))
1192e4b17023SJohn Marino   // will eventually result in undefined behaviour, attempting to
1193e4b17023SJohn Marino   // delete the same object twice.
1194e4b17023SJohn Marino   /// static_pointer_cast
1195e4b17023SJohn Marino   template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1196e4b17023SJohn Marino     inline __shared_ptr<_Tp, _Lp>
1197e4b17023SJohn Marino     static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1198e4b17023SJohn Marino     { return __shared_ptr<_Tp, _Lp>(__r, static_cast<_Tp*>(__r.get())); }
1199e4b17023SJohn Marino 
1200e4b17023SJohn Marino   // The seemingly equivalent code:
1201e4b17023SJohn Marino   // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
1202e4b17023SJohn Marino   // will eventually result in undefined behaviour, attempting to
1203e4b17023SJohn Marino   // delete the same object twice.
1204e4b17023SJohn Marino   /// const_pointer_cast
1205e4b17023SJohn Marino   template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1206e4b17023SJohn Marino     inline __shared_ptr<_Tp, _Lp>
1207e4b17023SJohn Marino     const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1208e4b17023SJohn Marino     { return __shared_ptr<_Tp, _Lp>(__r, const_cast<_Tp*>(__r.get())); }
1209e4b17023SJohn Marino 
1210e4b17023SJohn Marino   // The seemingly equivalent code:
1211e4b17023SJohn Marino   // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
1212e4b17023SJohn Marino   // will eventually result in undefined behaviour, attempting to
1213e4b17023SJohn Marino   // delete the same object twice.
1214e4b17023SJohn Marino   /// dynamic_pointer_cast
1215e4b17023SJohn Marino   template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1216e4b17023SJohn Marino     inline __shared_ptr<_Tp, _Lp>
1217e4b17023SJohn Marino     dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1218e4b17023SJohn Marino     {
1219e4b17023SJohn Marino       if (_Tp* __p = dynamic_cast<_Tp*>(__r.get()))
1220e4b17023SJohn Marino 	return __shared_ptr<_Tp, _Lp>(__r, __p);
1221e4b17023SJohn Marino       return __shared_ptr<_Tp, _Lp>();
1222e4b17023SJohn Marino     }
1223e4b17023SJohn Marino 
1224e4b17023SJohn Marino 
1225e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1226e4b17023SJohn Marino     class __weak_ptr
1227e4b17023SJohn Marino     {
1228e4b17023SJohn Marino     public:
1229e4b17023SJohn Marino       typedef _Tp element_type;
1230e4b17023SJohn Marino 
1231e4b17023SJohn Marino       constexpr __weak_ptr() noexcept
1232e4b17023SJohn Marino       : _M_ptr(0), _M_refcount()
1233e4b17023SJohn Marino       { }
1234e4b17023SJohn Marino 
1235e4b17023SJohn Marino       __weak_ptr(const __weak_ptr&) noexcept = default;
1236e4b17023SJohn Marino       __weak_ptr& operator=(const __weak_ptr&) noexcept = default;
1237e4b17023SJohn Marino       ~__weak_ptr() = default;
1238e4b17023SJohn Marino 
1239e4b17023SJohn Marino       // The "obvious" converting constructor implementation:
1240e4b17023SJohn Marino       //
1241e4b17023SJohn Marino       //  template<typename _Tp1>
1242e4b17023SJohn Marino       //    __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
1243e4b17023SJohn Marino       //    : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
1244e4b17023SJohn Marino       //    { }
1245e4b17023SJohn Marino       //
1246e4b17023SJohn Marino       // has a serious problem.
1247e4b17023SJohn Marino       //
1248e4b17023SJohn Marino       //  __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr)
1249e4b17023SJohn Marino       //  conversion may require access to *__r._M_ptr (virtual inheritance).
1250e4b17023SJohn Marino       //
1251e4b17023SJohn Marino       // It is not possible to avoid spurious access violations since
1252e4b17023SJohn Marino       // in multithreaded programs __r._M_ptr may be invalidated at any point.
1253e4b17023SJohn Marino       template<typename _Tp1, typename = typename
1254e4b17023SJohn Marino 	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
1255e4b17023SJohn Marino 	__weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
1256e4b17023SJohn Marino 	: _M_refcount(__r._M_refcount)
1257e4b17023SJohn Marino         { _M_ptr = __r.lock().get(); }
1258e4b17023SJohn Marino 
1259e4b17023SJohn Marino       template<typename _Tp1, typename = typename
1260e4b17023SJohn Marino 	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
1261e4b17023SJohn Marino 	__weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1262e4b17023SJohn Marino 	: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
1263e4b17023SJohn Marino 	{ }
1264e4b17023SJohn Marino 
1265e4b17023SJohn Marino       template<typename _Tp1>
1266e4b17023SJohn Marino 	__weak_ptr&
1267e4b17023SJohn Marino 	operator=(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
1268e4b17023SJohn Marino 	{
1269e4b17023SJohn Marino 	  _M_ptr = __r.lock().get();
1270e4b17023SJohn Marino 	  _M_refcount = __r._M_refcount;
1271e4b17023SJohn Marino 	  return *this;
1272e4b17023SJohn Marino 	}
1273e4b17023SJohn Marino 
1274e4b17023SJohn Marino       template<typename _Tp1>
1275e4b17023SJohn Marino 	__weak_ptr&
1276e4b17023SJohn Marino 	operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1277e4b17023SJohn Marino 	{
1278e4b17023SJohn Marino 	  _M_ptr = __r._M_ptr;
1279e4b17023SJohn Marino 	  _M_refcount = __r._M_refcount;
1280e4b17023SJohn Marino 	  return *this;
1281e4b17023SJohn Marino 	}
1282e4b17023SJohn Marino 
1283e4b17023SJohn Marino       __shared_ptr<_Tp, _Lp>
1284e4b17023SJohn Marino       lock() const noexcept
1285e4b17023SJohn Marino       {
1286e4b17023SJohn Marino #ifdef __GTHREADS
1287e4b17023SJohn Marino 	// Optimization: avoid throw overhead.
1288e4b17023SJohn Marino 	if (expired())
1289e4b17023SJohn Marino 	  return __shared_ptr<element_type, _Lp>();
1290e4b17023SJohn Marino 
1291e4b17023SJohn Marino 	__try
1292e4b17023SJohn Marino 	  {
1293e4b17023SJohn Marino 	    return __shared_ptr<element_type, _Lp>(*this);
1294e4b17023SJohn Marino 	  }
1295e4b17023SJohn Marino 	__catch(const bad_weak_ptr&)
1296e4b17023SJohn Marino 	  {
1297e4b17023SJohn Marino 	    // Q: How can we get here?
1298e4b17023SJohn Marino 	    // A: Another thread may have invalidated r after the
1299e4b17023SJohn Marino 	    //    use_count test above.
1300e4b17023SJohn Marino 	    return __shared_ptr<element_type, _Lp>();
1301e4b17023SJohn Marino 	  }
1302e4b17023SJohn Marino 
1303e4b17023SJohn Marino #else
1304e4b17023SJohn Marino 	// Optimization: avoid try/catch overhead when single threaded.
1305e4b17023SJohn Marino 	return expired() ? __shared_ptr<element_type, _Lp>()
1306e4b17023SJohn Marino 			 : __shared_ptr<element_type, _Lp>(*this);
1307e4b17023SJohn Marino 
1308e4b17023SJohn Marino #endif
1309e4b17023SJohn Marino       } // XXX MT
1310e4b17023SJohn Marino 
1311e4b17023SJohn Marino       long
1312e4b17023SJohn Marino       use_count() const noexcept
1313e4b17023SJohn Marino       { return _M_refcount._M_get_use_count(); }
1314e4b17023SJohn Marino 
1315e4b17023SJohn Marino       bool
1316e4b17023SJohn Marino       expired() const noexcept
1317e4b17023SJohn Marino       { return _M_refcount._M_get_use_count() == 0; }
1318e4b17023SJohn Marino 
1319e4b17023SJohn Marino       template<typename _Tp1>
1320e4b17023SJohn Marino 	bool
1321e4b17023SJohn Marino 	owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const
1322e4b17023SJohn Marino 	{ return _M_refcount._M_less(__rhs._M_refcount); }
1323e4b17023SJohn Marino 
1324e4b17023SJohn Marino       template<typename _Tp1>
1325e4b17023SJohn Marino 	bool
1326e4b17023SJohn Marino 	owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const
1327e4b17023SJohn Marino 	{ return _M_refcount._M_less(__rhs._M_refcount); }
1328e4b17023SJohn Marino 
1329e4b17023SJohn Marino       void
1330e4b17023SJohn Marino       reset() noexcept
1331e4b17023SJohn Marino       { __weak_ptr().swap(*this); }
1332e4b17023SJohn Marino 
1333e4b17023SJohn Marino       void
1334e4b17023SJohn Marino       swap(__weak_ptr& __s) noexcept
1335e4b17023SJohn Marino       {
1336e4b17023SJohn Marino 	std::swap(_M_ptr, __s._M_ptr);
1337e4b17023SJohn Marino 	_M_refcount._M_swap(__s._M_refcount);
1338e4b17023SJohn Marino       }
1339e4b17023SJohn Marino 
1340e4b17023SJohn Marino     private:
1341e4b17023SJohn Marino       // Used by __enable_shared_from_this.
1342e4b17023SJohn Marino       void
1343e4b17023SJohn Marino       _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) noexcept
1344e4b17023SJohn Marino       {
1345e4b17023SJohn Marino 	_M_ptr = __ptr;
1346e4b17023SJohn Marino 	_M_refcount = __refcount;
1347e4b17023SJohn Marino       }
1348e4b17023SJohn Marino 
1349e4b17023SJohn Marino       template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
1350e4b17023SJohn Marino       template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
1351e4b17023SJohn Marino       friend class __enable_shared_from_this<_Tp, _Lp>;
1352e4b17023SJohn Marino       friend class enable_shared_from_this<_Tp>;
1353e4b17023SJohn Marino 
1354e4b17023SJohn Marino       _Tp*	 	 _M_ptr;         // Contained pointer.
1355e4b17023SJohn Marino       __weak_count<_Lp>  _M_refcount;    // Reference counter.
1356e4b17023SJohn Marino     };
1357e4b17023SJohn Marino 
1358e4b17023SJohn Marino   // 20.8.13.3.7 weak_ptr specialized algorithms.
1359e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1360e4b17023SJohn Marino     inline void
1361e4b17023SJohn Marino     swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) noexcept
1362e4b17023SJohn Marino     { __a.swap(__b); }
1363e4b17023SJohn Marino 
1364e4b17023SJohn Marino   template<typename _Tp, typename _Tp1>
1365e4b17023SJohn Marino     struct _Sp_owner_less : public binary_function<_Tp, _Tp, bool>
1366e4b17023SJohn Marino     {
1367e4b17023SJohn Marino       bool
1368e4b17023SJohn Marino       operator()(const _Tp& __lhs, const _Tp& __rhs) const
1369e4b17023SJohn Marino       { return __lhs.owner_before(__rhs); }
1370e4b17023SJohn Marino 
1371e4b17023SJohn Marino       bool
1372e4b17023SJohn Marino       operator()(const _Tp& __lhs, const _Tp1& __rhs) const
1373e4b17023SJohn Marino       { return __lhs.owner_before(__rhs); }
1374e4b17023SJohn Marino 
1375e4b17023SJohn Marino       bool
1376e4b17023SJohn Marino       operator()(const _Tp1& __lhs, const _Tp& __rhs) const
1377e4b17023SJohn Marino       { return __lhs.owner_before(__rhs); }
1378e4b17023SJohn Marino     };
1379e4b17023SJohn Marino 
1380e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1381e4b17023SJohn Marino     struct owner_less<__shared_ptr<_Tp, _Lp>>
1382e4b17023SJohn Marino     : public _Sp_owner_less<__shared_ptr<_Tp, _Lp>, __weak_ptr<_Tp, _Lp>>
1383e4b17023SJohn Marino     { };
1384e4b17023SJohn Marino 
1385e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1386e4b17023SJohn Marino     struct owner_less<__weak_ptr<_Tp, _Lp>>
1387e4b17023SJohn Marino     : public _Sp_owner_less<__weak_ptr<_Tp, _Lp>, __shared_ptr<_Tp, _Lp>>
1388e4b17023SJohn Marino     { };
1389e4b17023SJohn Marino 
1390e4b17023SJohn Marino 
1391e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1392e4b17023SJohn Marino     class __enable_shared_from_this
1393e4b17023SJohn Marino     {
1394e4b17023SJohn Marino     protected:
1395e4b17023SJohn Marino       constexpr __enable_shared_from_this() noexcept { }
1396e4b17023SJohn Marino 
1397e4b17023SJohn Marino       __enable_shared_from_this(const __enable_shared_from_this&) noexcept { }
1398e4b17023SJohn Marino 
1399e4b17023SJohn Marino       __enable_shared_from_this&
1400e4b17023SJohn Marino       operator=(const __enable_shared_from_this&) noexcept
1401e4b17023SJohn Marino       { return *this; }
1402e4b17023SJohn Marino 
1403e4b17023SJohn Marino       ~__enable_shared_from_this() { }
1404e4b17023SJohn Marino 
1405e4b17023SJohn Marino     public:
1406e4b17023SJohn Marino       __shared_ptr<_Tp, _Lp>
1407e4b17023SJohn Marino       shared_from_this()
1408e4b17023SJohn Marino       { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); }
1409e4b17023SJohn Marino 
1410e4b17023SJohn Marino       __shared_ptr<const _Tp, _Lp>
1411e4b17023SJohn Marino       shared_from_this() const
1412e4b17023SJohn Marino       { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); }
1413e4b17023SJohn Marino 
1414e4b17023SJohn Marino     private:
1415e4b17023SJohn Marino       template<typename _Tp1>
1416e4b17023SJohn Marino 	void
1417e4b17023SJohn Marino 	_M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const noexcept
1418e4b17023SJohn Marino 	{ _M_weak_this._M_assign(__p, __n); }
1419e4b17023SJohn Marino 
1420e4b17023SJohn Marino       template<typename _Tp1>
1421e4b17023SJohn Marino 	friend void
1422e4b17023SJohn Marino 	__enable_shared_from_this_helper(const __shared_count<_Lp>& __pn,
1423e4b17023SJohn Marino 					 const __enable_shared_from_this* __pe,
1424e4b17023SJohn Marino 					 const _Tp1* __px) noexcept
1425e4b17023SJohn Marino 	{
1426e4b17023SJohn Marino 	  if (__pe != 0)
1427e4b17023SJohn Marino 	    __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
1428e4b17023SJohn Marino 	}
1429e4b17023SJohn Marino 
1430e4b17023SJohn Marino       mutable __weak_ptr<_Tp, _Lp>  _M_weak_this;
1431e4b17023SJohn Marino     };
1432e4b17023SJohn Marino 
1433e4b17023SJohn Marino 
1434e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp, typename _Alloc, typename... _Args>
1435e4b17023SJohn Marino     inline __shared_ptr<_Tp, _Lp>
1436e4b17023SJohn Marino     __allocate_shared(const _Alloc& __a, _Args&&... __args)
1437e4b17023SJohn Marino     {
1438e4b17023SJohn Marino       return __shared_ptr<_Tp, _Lp>(_Sp_make_shared_tag(), __a,
1439e4b17023SJohn Marino 				    std::forward<_Args>(__args)...);
1440e4b17023SJohn Marino     }
1441e4b17023SJohn Marino 
1442e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp, typename... _Args>
1443e4b17023SJohn Marino     inline __shared_ptr<_Tp, _Lp>
1444e4b17023SJohn Marino     __make_shared(_Args&&... __args)
1445e4b17023SJohn Marino     {
1446e4b17023SJohn Marino       typedef typename std::remove_const<_Tp>::type _Tp_nc;
1447e4b17023SJohn Marino       return std::__allocate_shared<_Tp, _Lp>(std::allocator<_Tp_nc>(),
1448e4b17023SJohn Marino 					      std::forward<_Args>(__args)...);
1449e4b17023SJohn Marino     }
1450e4b17023SJohn Marino 
1451e4b17023SJohn Marino   /// std::hash specialization for __shared_ptr.
1452e4b17023SJohn Marino   template<typename _Tp, _Lock_policy _Lp>
1453e4b17023SJohn Marino     struct hash<__shared_ptr<_Tp, _Lp>>
1454e4b17023SJohn Marino     : public __hash_base<size_t, __shared_ptr<_Tp, _Lp>>
1455e4b17023SJohn Marino     {
1456e4b17023SJohn Marino       size_t
1457e4b17023SJohn Marino       operator()(const __shared_ptr<_Tp, _Lp>& __s) const noexcept
1458e4b17023SJohn Marino       { return std::hash<_Tp*>()(__s.get()); }
1459e4b17023SJohn Marino     };
1460e4b17023SJohn Marino 
1461e4b17023SJohn Marino _GLIBCXX_END_NAMESPACE_VERSION
1462e4b17023SJohn Marino } // namespace
1463e4b17023SJohn Marino 
1464e4b17023SJohn Marino #endif // _SHARED_PTR_BASE_H
1465