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