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