11debfc3dSmrg // shared_ptr and weak_ptr implementation details -*- C++ -*-
21debfc3dSmrg
38feb0f0bSmrg // Copyright (C) 2007-2020 Free Software Foundation, Inc.
41debfc3dSmrg //
51debfc3dSmrg // This file is part of the GNU ISO C++ Library. This library is free
61debfc3dSmrg // software; you can redistribute it and/or modify it under the
71debfc3dSmrg // terms of the GNU General Public License as published by the
81debfc3dSmrg // Free Software Foundation; either version 3, or (at your option)
91debfc3dSmrg // any later version.
101debfc3dSmrg
111debfc3dSmrg // This library is distributed in the hope that it will be useful,
121debfc3dSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
131debfc3dSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
141debfc3dSmrg // GNU General Public License for more details.
151debfc3dSmrg
161debfc3dSmrg // Under Section 7 of GPL version 3, you are granted additional
171debfc3dSmrg // permissions described in the GCC Runtime Library Exception, version
181debfc3dSmrg // 3.1, as published by the Free Software Foundation.
191debfc3dSmrg
201debfc3dSmrg // You should have received a copy of the GNU General Public License and
211debfc3dSmrg // a copy of the GCC Runtime Library Exception along with this program;
221debfc3dSmrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
231debfc3dSmrg // <http://www.gnu.org/licenses/>.
241debfc3dSmrg
251debfc3dSmrg // GCC Note: Based on files from version 1.32.0 of the Boost library.
261debfc3dSmrg
271debfc3dSmrg // shared_count.hpp
281debfc3dSmrg // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
291debfc3dSmrg
301debfc3dSmrg // shared_ptr.hpp
311debfc3dSmrg // Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
321debfc3dSmrg // Copyright (C) 2001, 2002, 2003 Peter Dimov
331debfc3dSmrg
341debfc3dSmrg // weak_ptr.hpp
351debfc3dSmrg // Copyright (C) 2001, 2002, 2003 Peter Dimov
361debfc3dSmrg
371debfc3dSmrg // enable_shared_from_this.hpp
381debfc3dSmrg // Copyright (C) 2002 Peter Dimov
391debfc3dSmrg
401debfc3dSmrg // Distributed under the Boost Software License, Version 1.0. (See
411debfc3dSmrg // accompanying file LICENSE_1_0.txt or copy at
421debfc3dSmrg // http://www.boost.org/LICENSE_1_0.txt)
431debfc3dSmrg
441debfc3dSmrg /** @file bits/shared_ptr_base.h
451debfc3dSmrg * This is an internal header file, included by other library headers.
461debfc3dSmrg * Do not attempt to use it directly. @headername{memory}
471debfc3dSmrg */
481debfc3dSmrg
491debfc3dSmrg #ifndef _SHARED_PTR_BASE_H
501debfc3dSmrg #define _SHARED_PTR_BASE_H 1
511debfc3dSmrg
521debfc3dSmrg #include <typeinfo>
531debfc3dSmrg #include <bits/allocated_ptr.h>
541debfc3dSmrg #include <bits/refwrap.h>
551debfc3dSmrg #include <bits/stl_function.h>
561debfc3dSmrg #include <ext/aligned_buffer.h>
578feb0f0bSmrg #if __cplusplus > 201703L
588feb0f0bSmrg # include <compare>
598feb0f0bSmrg #endif
601debfc3dSmrg
_GLIBCXX_VISIBILITY(default)611debfc3dSmrg namespace std _GLIBCXX_VISIBILITY(default)
621debfc3dSmrg {
631debfc3dSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
641debfc3dSmrg
651debfc3dSmrg #if _GLIBCXX_USE_DEPRECATED
66a2dc1f3fSmrg #pragma GCC diagnostic push
67a2dc1f3fSmrg #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
681debfc3dSmrg template<typename> class auto_ptr;
69a2dc1f3fSmrg #pragma GCC diagnostic pop
701debfc3dSmrg #endif
711debfc3dSmrg
721debfc3dSmrg /**
731debfc3dSmrg * @brief Exception possibly thrown by @c shared_ptr.
741debfc3dSmrg * @ingroup exceptions
751debfc3dSmrg */
761debfc3dSmrg class bad_weak_ptr : public std::exception
771debfc3dSmrg {
781debfc3dSmrg public:
791debfc3dSmrg virtual char const* what() const noexcept;
801debfc3dSmrg
811debfc3dSmrg virtual ~bad_weak_ptr() noexcept;
821debfc3dSmrg };
831debfc3dSmrg
841debfc3dSmrg // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
851debfc3dSmrg inline void
861debfc3dSmrg __throw_bad_weak_ptr()
871debfc3dSmrg { _GLIBCXX_THROW_OR_ABORT(bad_weak_ptr()); }
881debfc3dSmrg
891debfc3dSmrg using __gnu_cxx::_Lock_policy;
901debfc3dSmrg using __gnu_cxx::__default_lock_policy;
911debfc3dSmrg using __gnu_cxx::_S_single;
921debfc3dSmrg using __gnu_cxx::_S_mutex;
931debfc3dSmrg using __gnu_cxx::_S_atomic;
941debfc3dSmrg
951debfc3dSmrg // Empty helper class except when the template argument is _S_mutex.
961debfc3dSmrg template<_Lock_policy _Lp>
971debfc3dSmrg class _Mutex_base
981debfc3dSmrg {
991debfc3dSmrg protected:
1001debfc3dSmrg // The atomic policy uses fully-fenced builtins, single doesn't care.
1011debfc3dSmrg enum { _S_need_barriers = 0 };
1021debfc3dSmrg };
1031debfc3dSmrg
1041debfc3dSmrg template<>
1051debfc3dSmrg class _Mutex_base<_S_mutex>
1061debfc3dSmrg : public __gnu_cxx::__mutex
1071debfc3dSmrg {
1081debfc3dSmrg protected:
1091debfc3dSmrg // This policy is used when atomic builtins are not available.
1101debfc3dSmrg // The replacement atomic operations might not have the necessary
1111debfc3dSmrg // memory barriers.
1121debfc3dSmrg enum { _S_need_barriers = 1 };
1131debfc3dSmrg };
1141debfc3dSmrg
1151debfc3dSmrg template<_Lock_policy _Lp = __default_lock_policy>
1161debfc3dSmrg class _Sp_counted_base
1171debfc3dSmrg : public _Mutex_base<_Lp>
1181debfc3dSmrg {
1191debfc3dSmrg public:
1201debfc3dSmrg _Sp_counted_base() noexcept
1211debfc3dSmrg : _M_use_count(1), _M_weak_count(1) { }
1221debfc3dSmrg
1231debfc3dSmrg virtual
1241debfc3dSmrg ~_Sp_counted_base() noexcept
1251debfc3dSmrg { }
1261debfc3dSmrg
1271debfc3dSmrg // Called when _M_use_count drops to zero, to release the resources
1281debfc3dSmrg // managed by *this.
1291debfc3dSmrg virtual void
1301debfc3dSmrg _M_dispose() noexcept = 0;
1311debfc3dSmrg
1321debfc3dSmrg // Called when _M_weak_count drops to zero.
1331debfc3dSmrg virtual void
1341debfc3dSmrg _M_destroy() noexcept
1351debfc3dSmrg { delete this; }
1361debfc3dSmrg
1371debfc3dSmrg virtual void*
1381debfc3dSmrg _M_get_deleter(const std::type_info&) noexcept = 0;
1391debfc3dSmrg
1401debfc3dSmrg void
1411debfc3dSmrg _M_add_ref_copy()
1421debfc3dSmrg { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
1431debfc3dSmrg
1441debfc3dSmrg void
1451debfc3dSmrg _M_add_ref_lock();
1461debfc3dSmrg
1471debfc3dSmrg bool
1481debfc3dSmrg _M_add_ref_lock_nothrow();
1491debfc3dSmrg
1501debfc3dSmrg void
1511debfc3dSmrg _M_release() noexcept
1521debfc3dSmrg {
1531debfc3dSmrg // Be race-detector-friendly. For more info see bits/c++config.
1541debfc3dSmrg _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
1551debfc3dSmrg if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
1561debfc3dSmrg {
1571debfc3dSmrg _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
1581debfc3dSmrg _M_dispose();
1591debfc3dSmrg // There must be a memory barrier between dispose() and destroy()
1601debfc3dSmrg // to ensure that the effects of dispose() are observed in the
1611debfc3dSmrg // thread that runs destroy().
1621debfc3dSmrg // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
1631debfc3dSmrg if (_Mutex_base<_Lp>::_S_need_barriers)
1641debfc3dSmrg {
1651debfc3dSmrg __atomic_thread_fence (__ATOMIC_ACQ_REL);
1661debfc3dSmrg }
1671debfc3dSmrg
1681debfc3dSmrg // Be race-detector-friendly. For more info see bits/c++config.
1691debfc3dSmrg _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
1701debfc3dSmrg if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
1711debfc3dSmrg -1) == 1)
1721debfc3dSmrg {
1731debfc3dSmrg _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
1741debfc3dSmrg _M_destroy();
1751debfc3dSmrg }
1761debfc3dSmrg }
1771debfc3dSmrg }
1781debfc3dSmrg
1791debfc3dSmrg void
1801debfc3dSmrg _M_weak_add_ref() noexcept
1811debfc3dSmrg { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
1821debfc3dSmrg
1831debfc3dSmrg void
1841debfc3dSmrg _M_weak_release() noexcept
1851debfc3dSmrg {
1861debfc3dSmrg // Be race-detector-friendly. For more info see bits/c++config.
1871debfc3dSmrg _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
1881debfc3dSmrg if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
1891debfc3dSmrg {
1901debfc3dSmrg _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
1911debfc3dSmrg if (_Mutex_base<_Lp>::_S_need_barriers)
1921debfc3dSmrg {
1931debfc3dSmrg // See _M_release(),
1941debfc3dSmrg // destroy() must observe results of dispose()
1951debfc3dSmrg __atomic_thread_fence (__ATOMIC_ACQ_REL);
1961debfc3dSmrg }
1971debfc3dSmrg _M_destroy();
1981debfc3dSmrg }
1991debfc3dSmrg }
2001debfc3dSmrg
2011debfc3dSmrg long
2021debfc3dSmrg _M_get_use_count() const noexcept
2031debfc3dSmrg {
2041debfc3dSmrg // No memory barrier is used here so there is no synchronization
2051debfc3dSmrg // with other threads.
2061debfc3dSmrg return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED);
2071debfc3dSmrg }
2081debfc3dSmrg
2091debfc3dSmrg private:
2101debfc3dSmrg _Sp_counted_base(_Sp_counted_base const&) = delete;
2111debfc3dSmrg _Sp_counted_base& operator=(_Sp_counted_base const&) = delete;
2121debfc3dSmrg
2131debfc3dSmrg _Atomic_word _M_use_count; // #shared
2141debfc3dSmrg _Atomic_word _M_weak_count; // #weak + (#shared != 0)
2151debfc3dSmrg };
2161debfc3dSmrg
2171debfc3dSmrg template<>
2181debfc3dSmrg inline void
2191debfc3dSmrg _Sp_counted_base<_S_single>::
2201debfc3dSmrg _M_add_ref_lock()
2211debfc3dSmrg {
2221debfc3dSmrg if (_M_use_count == 0)
2231debfc3dSmrg __throw_bad_weak_ptr();
2241debfc3dSmrg ++_M_use_count;
2251debfc3dSmrg }
2261debfc3dSmrg
2271debfc3dSmrg template<>
2281debfc3dSmrg inline void
2291debfc3dSmrg _Sp_counted_base<_S_mutex>::
2301debfc3dSmrg _M_add_ref_lock()
2311debfc3dSmrg {
2321debfc3dSmrg __gnu_cxx::__scoped_lock sentry(*this);
2331debfc3dSmrg if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
2341debfc3dSmrg {
2351debfc3dSmrg _M_use_count = 0;
2361debfc3dSmrg __throw_bad_weak_ptr();
2371debfc3dSmrg }
2381debfc3dSmrg }
2391debfc3dSmrg
2401debfc3dSmrg template<>
2411debfc3dSmrg inline void
2421debfc3dSmrg _Sp_counted_base<_S_atomic>::
2431debfc3dSmrg _M_add_ref_lock()
2441debfc3dSmrg {
2451debfc3dSmrg // Perform lock-free add-if-not-zero operation.
2461debfc3dSmrg _Atomic_word __count = _M_get_use_count();
2471debfc3dSmrg do
2481debfc3dSmrg {
2491debfc3dSmrg if (__count == 0)
2501debfc3dSmrg __throw_bad_weak_ptr();
2511debfc3dSmrg // Replace the current counter value with the old value + 1, as
2521debfc3dSmrg // long as it's not changed meanwhile.
2531debfc3dSmrg }
2541debfc3dSmrg while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
2551debfc3dSmrg true, __ATOMIC_ACQ_REL,
2561debfc3dSmrg __ATOMIC_RELAXED));
2571debfc3dSmrg }
2581debfc3dSmrg
2591debfc3dSmrg template<>
2601debfc3dSmrg inline bool
2611debfc3dSmrg _Sp_counted_base<_S_single>::
2621debfc3dSmrg _M_add_ref_lock_nothrow()
2631debfc3dSmrg {
2641debfc3dSmrg if (_M_use_count == 0)
2651debfc3dSmrg return false;
2661debfc3dSmrg ++_M_use_count;
2671debfc3dSmrg return true;
2681debfc3dSmrg }
2691debfc3dSmrg
2701debfc3dSmrg template<>
2711debfc3dSmrg inline bool
2721debfc3dSmrg _Sp_counted_base<_S_mutex>::
2731debfc3dSmrg _M_add_ref_lock_nothrow()
2741debfc3dSmrg {
2751debfc3dSmrg __gnu_cxx::__scoped_lock sentry(*this);
2761debfc3dSmrg if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
2771debfc3dSmrg {
2781debfc3dSmrg _M_use_count = 0;
2791debfc3dSmrg return false;
2801debfc3dSmrg }
2811debfc3dSmrg return true;
2821debfc3dSmrg }
2831debfc3dSmrg
2841debfc3dSmrg template<>
2851debfc3dSmrg inline bool
2861debfc3dSmrg _Sp_counted_base<_S_atomic>::
2871debfc3dSmrg _M_add_ref_lock_nothrow()
2881debfc3dSmrg {
2891debfc3dSmrg // Perform lock-free add-if-not-zero operation.
2901debfc3dSmrg _Atomic_word __count = _M_get_use_count();
2911debfc3dSmrg do
2921debfc3dSmrg {
2931debfc3dSmrg if (__count == 0)
2941debfc3dSmrg return false;
2951debfc3dSmrg // Replace the current counter value with the old value + 1, as
2961debfc3dSmrg // long as it's not changed meanwhile.
2971debfc3dSmrg }
2981debfc3dSmrg while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
2991debfc3dSmrg true, __ATOMIC_ACQ_REL,
3001debfc3dSmrg __ATOMIC_RELAXED));
3011debfc3dSmrg return true;
3021debfc3dSmrg }
3031debfc3dSmrg
3041debfc3dSmrg template<>
3051debfc3dSmrg inline void
3061debfc3dSmrg _Sp_counted_base<_S_single>::_M_add_ref_copy()
3071debfc3dSmrg { ++_M_use_count; }
3081debfc3dSmrg
3091debfc3dSmrg template<>
3101debfc3dSmrg inline void
3111debfc3dSmrg _Sp_counted_base<_S_single>::_M_release() noexcept
3121debfc3dSmrg {
3131debfc3dSmrg if (--_M_use_count == 0)
3141debfc3dSmrg {
3151debfc3dSmrg _M_dispose();
3161debfc3dSmrg if (--_M_weak_count == 0)
3171debfc3dSmrg _M_destroy();
3181debfc3dSmrg }
3191debfc3dSmrg }
3201debfc3dSmrg
3211debfc3dSmrg template<>
3221debfc3dSmrg inline void
3231debfc3dSmrg _Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept
3241debfc3dSmrg { ++_M_weak_count; }
3251debfc3dSmrg
3261debfc3dSmrg template<>
3271debfc3dSmrg inline void
3281debfc3dSmrg _Sp_counted_base<_S_single>::_M_weak_release() noexcept
3291debfc3dSmrg {
3301debfc3dSmrg if (--_M_weak_count == 0)
3311debfc3dSmrg _M_destroy();
3321debfc3dSmrg }
3331debfc3dSmrg
3341debfc3dSmrg template<>
3351debfc3dSmrg inline long
3361debfc3dSmrg _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept
3371debfc3dSmrg { return _M_use_count; }
3381debfc3dSmrg
3391debfc3dSmrg
3401debfc3dSmrg // Forward declarations.
3411debfc3dSmrg template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
3421debfc3dSmrg class __shared_ptr;
3431debfc3dSmrg
3441debfc3dSmrg template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
3451debfc3dSmrg class __weak_ptr;
3461debfc3dSmrg
3471debfc3dSmrg template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
3481debfc3dSmrg class __enable_shared_from_this;
3491debfc3dSmrg
3501debfc3dSmrg template<typename _Tp>
3511debfc3dSmrg class shared_ptr;
3521debfc3dSmrg
3531debfc3dSmrg template<typename _Tp>
3541debfc3dSmrg class weak_ptr;
3551debfc3dSmrg
3561debfc3dSmrg template<typename _Tp>
3571debfc3dSmrg struct owner_less;
3581debfc3dSmrg
3591debfc3dSmrg template<typename _Tp>
3601debfc3dSmrg class enable_shared_from_this;
3611debfc3dSmrg
3621debfc3dSmrg template<_Lock_policy _Lp = __default_lock_policy>
3631debfc3dSmrg class __weak_count;
3641debfc3dSmrg
3651debfc3dSmrg template<_Lock_policy _Lp = __default_lock_policy>
3661debfc3dSmrg class __shared_count;
3671debfc3dSmrg
3681debfc3dSmrg
3691debfc3dSmrg // Counted ptr with no deleter or allocator support
3701debfc3dSmrg template<typename _Ptr, _Lock_policy _Lp>
3711debfc3dSmrg class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>
3721debfc3dSmrg {
3731debfc3dSmrg public:
3741debfc3dSmrg explicit
3751debfc3dSmrg _Sp_counted_ptr(_Ptr __p) noexcept
3761debfc3dSmrg : _M_ptr(__p) { }
3771debfc3dSmrg
3781debfc3dSmrg virtual void
3791debfc3dSmrg _M_dispose() noexcept
3801debfc3dSmrg { delete _M_ptr; }
3811debfc3dSmrg
3821debfc3dSmrg virtual void
3831debfc3dSmrg _M_destroy() noexcept
3841debfc3dSmrg { delete this; }
3851debfc3dSmrg
3861debfc3dSmrg virtual void*
3871debfc3dSmrg _M_get_deleter(const std::type_info&) noexcept
3881debfc3dSmrg { return nullptr; }
3891debfc3dSmrg
3901debfc3dSmrg _Sp_counted_ptr(const _Sp_counted_ptr&) = delete;
3911debfc3dSmrg _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete;
3921debfc3dSmrg
3931debfc3dSmrg private:
3941debfc3dSmrg _Ptr _M_ptr;
3951debfc3dSmrg };
3961debfc3dSmrg
3971debfc3dSmrg template<>
3981debfc3dSmrg inline void
3991debfc3dSmrg _Sp_counted_ptr<nullptr_t, _S_single>::_M_dispose() noexcept { }
4001debfc3dSmrg
4011debfc3dSmrg template<>
4021debfc3dSmrg inline void
4031debfc3dSmrg _Sp_counted_ptr<nullptr_t, _S_mutex>::_M_dispose() noexcept { }
4041debfc3dSmrg
4051debfc3dSmrg template<>
4061debfc3dSmrg inline void
4071debfc3dSmrg _Sp_counted_ptr<nullptr_t, _S_atomic>::_M_dispose() noexcept { }
4081debfc3dSmrg
4091debfc3dSmrg template<int _Nm, typename _Tp,
4101debfc3dSmrg bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)>
4111debfc3dSmrg struct _Sp_ebo_helper;
4121debfc3dSmrg
4131debfc3dSmrg /// Specialization using EBO.
4141debfc3dSmrg template<int _Nm, typename _Tp>
4151debfc3dSmrg struct _Sp_ebo_helper<_Nm, _Tp, true> : private _Tp
4161debfc3dSmrg {
4171debfc3dSmrg explicit _Sp_ebo_helper(const _Tp& __tp) : _Tp(__tp) { }
4181debfc3dSmrg explicit _Sp_ebo_helper(_Tp&& __tp) : _Tp(std::move(__tp)) { }
4191debfc3dSmrg
4201debfc3dSmrg static _Tp&
4211debfc3dSmrg _S_get(_Sp_ebo_helper& __eboh) { return static_cast<_Tp&>(__eboh); }
4221debfc3dSmrg };
4231debfc3dSmrg
4241debfc3dSmrg /// Specialization not using EBO.
4251debfc3dSmrg template<int _Nm, typename _Tp>
4261debfc3dSmrg struct _Sp_ebo_helper<_Nm, _Tp, false>
4271debfc3dSmrg {
4281debfc3dSmrg explicit _Sp_ebo_helper(const _Tp& __tp) : _M_tp(__tp) { }
4291debfc3dSmrg explicit _Sp_ebo_helper(_Tp&& __tp) : _M_tp(std::move(__tp)) { }
4301debfc3dSmrg
4311debfc3dSmrg static _Tp&
4321debfc3dSmrg _S_get(_Sp_ebo_helper& __eboh)
4331debfc3dSmrg { return __eboh._M_tp; }
4341debfc3dSmrg
4351debfc3dSmrg private:
4361debfc3dSmrg _Tp _M_tp;
4371debfc3dSmrg };
4381debfc3dSmrg
4391debfc3dSmrg // Support for custom deleter and/or allocator
4401debfc3dSmrg template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp>
4411debfc3dSmrg class _Sp_counted_deleter final : public _Sp_counted_base<_Lp>
4421debfc3dSmrg {
4431debfc3dSmrg class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc>
4441debfc3dSmrg {
4451debfc3dSmrg typedef _Sp_ebo_helper<0, _Deleter> _Del_base;
4461debfc3dSmrg typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base;
4471debfc3dSmrg
4481debfc3dSmrg public:
4491debfc3dSmrg _Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
4501debfc3dSmrg : _M_ptr(__p), _Del_base(std::move(__d)), _Alloc_base(__a)
4511debfc3dSmrg { }
4521debfc3dSmrg
4531debfc3dSmrg _Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); }
4541debfc3dSmrg _Alloc& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); }
4551debfc3dSmrg
4561debfc3dSmrg _Ptr _M_ptr;
4571debfc3dSmrg };
4581debfc3dSmrg
4591debfc3dSmrg public:
4601debfc3dSmrg using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_deleter>;
4611debfc3dSmrg
4621debfc3dSmrg // __d(__p) must not throw.
4631debfc3dSmrg _Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept
4641debfc3dSmrg : _M_impl(__p, std::move(__d), _Alloc()) { }
4651debfc3dSmrg
4661debfc3dSmrg // __d(__p) must not throw.
4671debfc3dSmrg _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
4681debfc3dSmrg : _M_impl(__p, std::move(__d), __a) { }
4691debfc3dSmrg
4701debfc3dSmrg ~_Sp_counted_deleter() noexcept { }
4711debfc3dSmrg
4721debfc3dSmrg virtual void
4731debfc3dSmrg _M_dispose() noexcept
4741debfc3dSmrg { _M_impl._M_del()(_M_impl._M_ptr); }
4751debfc3dSmrg
4761debfc3dSmrg virtual void
4771debfc3dSmrg _M_destroy() noexcept
4781debfc3dSmrg {
4791debfc3dSmrg __allocator_type __a(_M_impl._M_alloc());
4801debfc3dSmrg __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
4811debfc3dSmrg this->~_Sp_counted_deleter();
4821debfc3dSmrg }
4831debfc3dSmrg
4841debfc3dSmrg virtual void*
4851debfc3dSmrg _M_get_deleter(const std::type_info& __ti) noexcept
4861debfc3dSmrg {
4871debfc3dSmrg #if __cpp_rtti
4881debfc3dSmrg // _GLIBCXX_RESOLVE_LIB_DEFECTS
4891debfc3dSmrg // 2400. shared_ptr's get_deleter() should use addressof()
4901debfc3dSmrg return __ti == typeid(_Deleter)
4911debfc3dSmrg ? std::__addressof(_M_impl._M_del())
4921debfc3dSmrg : nullptr;
4931debfc3dSmrg #else
4941debfc3dSmrg return nullptr;
4951debfc3dSmrg #endif
4961debfc3dSmrg }
4971debfc3dSmrg
4981debfc3dSmrg private:
4991debfc3dSmrg _Impl _M_impl;
5001debfc3dSmrg };
5011debfc3dSmrg
5021debfc3dSmrg // helpers for make_shared / allocate_shared
5031debfc3dSmrg
504a2dc1f3fSmrg struct _Sp_make_shared_tag
505a2dc1f3fSmrg {
506a2dc1f3fSmrg private:
507a2dc1f3fSmrg template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
508a2dc1f3fSmrg friend class _Sp_counted_ptr_inplace;
509a2dc1f3fSmrg
510a2dc1f3fSmrg static const type_info&
511a2dc1f3fSmrg _S_ti() noexcept _GLIBCXX_VISIBILITY(default)
512a2dc1f3fSmrg {
513a2dc1f3fSmrg alignas(type_info) static constexpr char __tag[sizeof(type_info)] = { };
514a2dc1f3fSmrg return reinterpret_cast<const type_info&>(__tag);
515a2dc1f3fSmrg }
516c0a68be4Smrg
517c0a68be4Smrg static bool _S_eq(const type_info&) noexcept;
518a2dc1f3fSmrg };
519a2dc1f3fSmrg
520a2dc1f3fSmrg template<typename _Alloc>
521a2dc1f3fSmrg struct _Sp_alloc_shared_tag
522a2dc1f3fSmrg {
523a2dc1f3fSmrg const _Alloc& _M_a;
524a2dc1f3fSmrg };
5251debfc3dSmrg
5261debfc3dSmrg template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
5271debfc3dSmrg class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp>
5281debfc3dSmrg {
5291debfc3dSmrg class _Impl : _Sp_ebo_helper<0, _Alloc>
5301debfc3dSmrg {
5311debfc3dSmrg typedef _Sp_ebo_helper<0, _Alloc> _A_base;
5321debfc3dSmrg
5331debfc3dSmrg public:
5341debfc3dSmrg explicit _Impl(_Alloc __a) noexcept : _A_base(__a) { }
5351debfc3dSmrg
5361debfc3dSmrg _Alloc& _M_alloc() noexcept { return _A_base::_S_get(*this); }
5371debfc3dSmrg
5381debfc3dSmrg __gnu_cxx::__aligned_buffer<_Tp> _M_storage;
5391debfc3dSmrg };
5401debfc3dSmrg
5411debfc3dSmrg public:
5421debfc3dSmrg using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>;
5431debfc3dSmrg
544c0a68be4Smrg // Alloc parameter is not a reference so doesn't alias anything in __args
5451debfc3dSmrg template<typename... _Args>
5461debfc3dSmrg _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args)
5471debfc3dSmrg : _M_impl(__a)
5481debfc3dSmrg {
5491debfc3dSmrg // _GLIBCXX_RESOLVE_LIB_DEFECTS
5501debfc3dSmrg // 2070. allocate_shared should use allocator_traits<A>::construct
5511debfc3dSmrg allocator_traits<_Alloc>::construct(__a, _M_ptr(),
5521debfc3dSmrg std::forward<_Args>(__args)...); // might throw
5531debfc3dSmrg }
5541debfc3dSmrg
5551debfc3dSmrg ~_Sp_counted_ptr_inplace() noexcept { }
5561debfc3dSmrg
5571debfc3dSmrg virtual void
5581debfc3dSmrg _M_dispose() noexcept
5591debfc3dSmrg {
5601debfc3dSmrg allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr());
5611debfc3dSmrg }
5621debfc3dSmrg
5631debfc3dSmrg // Override because the allocator needs to know the dynamic type
5641debfc3dSmrg virtual void
5651debfc3dSmrg _M_destroy() noexcept
5661debfc3dSmrg {
5671debfc3dSmrg __allocator_type __a(_M_impl._M_alloc());
5681debfc3dSmrg __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
5691debfc3dSmrg this->~_Sp_counted_ptr_inplace();
5701debfc3dSmrg }
5711debfc3dSmrg
572a2dc1f3fSmrg private:
573a2dc1f3fSmrg friend class __shared_count<_Lp>; // To be able to call _M_ptr().
574a2dc1f3fSmrg
575a2dc1f3fSmrg // No longer used, but code compiled against old libstdc++ headers
576a2dc1f3fSmrg // might still call it from __shared_ptr ctor to get the pointer out.
5771debfc3dSmrg virtual void*
578a2dc1f3fSmrg _M_get_deleter(const std::type_info& __ti) noexcept override
5791debfc3dSmrg {
580c0a68be4Smrg auto __ptr = const_cast<typename remove_cv<_Tp>::type*>(_M_ptr());
581a2dc1f3fSmrg // Check for the fake type_info first, so we don't try to access it
582c0a68be4Smrg // as a real type_info object. Otherwise, check if it's the real
583c0a68be4Smrg // type_info for this class. With RTTI enabled we can check directly,
584c0a68be4Smrg // or call a library function to do it.
585c0a68be4Smrg if (&__ti == &_Sp_make_shared_tag::_S_ti()
586c0a68be4Smrg ||
587a2dc1f3fSmrg #if __cpp_rtti
588c0a68be4Smrg __ti == typeid(_Sp_make_shared_tag)
589a2dc1f3fSmrg #else
590c0a68be4Smrg _Sp_make_shared_tag::_S_eq(__ti)
5911debfc3dSmrg #endif
592c0a68be4Smrg )
593c0a68be4Smrg return __ptr;
5941debfc3dSmrg return nullptr;
5951debfc3dSmrg }
5961debfc3dSmrg
5971debfc3dSmrg _Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); }
5981debfc3dSmrg
5991debfc3dSmrg _Impl _M_impl;
6001debfc3dSmrg };
6011debfc3dSmrg
6021debfc3dSmrg // The default deleter for shared_ptr<T[]> and shared_ptr<T[N]>.
6031debfc3dSmrg struct __sp_array_delete
6041debfc3dSmrg {
6051debfc3dSmrg template<typename _Yp>
6061debfc3dSmrg void operator()(_Yp* __p) const { delete[] __p; }
6071debfc3dSmrg };
6081debfc3dSmrg
6091debfc3dSmrg template<_Lock_policy _Lp>
6101debfc3dSmrg class __shared_count
6111debfc3dSmrg {
612a2dc1f3fSmrg template<typename _Tp>
613a2dc1f3fSmrg struct __not_alloc_shared_tag { using type = void; };
614a2dc1f3fSmrg
615a2dc1f3fSmrg template<typename _Tp>
616a2dc1f3fSmrg struct __not_alloc_shared_tag<_Sp_alloc_shared_tag<_Tp>> { };
617a2dc1f3fSmrg
6181debfc3dSmrg public:
6191debfc3dSmrg constexpr __shared_count() noexcept : _M_pi(0)
6201debfc3dSmrg { }
6211debfc3dSmrg
6221debfc3dSmrg template<typename _Ptr>
6231debfc3dSmrg explicit
6241debfc3dSmrg __shared_count(_Ptr __p) : _M_pi(0)
6251debfc3dSmrg {
6261debfc3dSmrg __try
6271debfc3dSmrg {
6281debfc3dSmrg _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);
6291debfc3dSmrg }
6301debfc3dSmrg __catch(...)
6311debfc3dSmrg {
6321debfc3dSmrg delete __p;
6331debfc3dSmrg __throw_exception_again;
6341debfc3dSmrg }
6351debfc3dSmrg }
6361debfc3dSmrg
6371debfc3dSmrg template<typename _Ptr>
6381debfc3dSmrg __shared_count(_Ptr __p, /* is_array = */ false_type)
6391debfc3dSmrg : __shared_count(__p)
6401debfc3dSmrg { }
6411debfc3dSmrg
6421debfc3dSmrg template<typename _Ptr>
6431debfc3dSmrg __shared_count(_Ptr __p, /* is_array = */ true_type)
6441debfc3dSmrg : __shared_count(__p, __sp_array_delete{}, allocator<void>())
6451debfc3dSmrg { }
6461debfc3dSmrg
647a2dc1f3fSmrg template<typename _Ptr, typename _Deleter,
648a2dc1f3fSmrg typename = typename __not_alloc_shared_tag<_Deleter>::type>
6491debfc3dSmrg __shared_count(_Ptr __p, _Deleter __d)
6501debfc3dSmrg : __shared_count(__p, std::move(__d), allocator<void>())
6511debfc3dSmrg { }
6521debfc3dSmrg
653a2dc1f3fSmrg template<typename _Ptr, typename _Deleter, typename _Alloc,
654a2dc1f3fSmrg typename = typename __not_alloc_shared_tag<_Deleter>::type>
6551debfc3dSmrg __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
6561debfc3dSmrg {
6571debfc3dSmrg typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
6581debfc3dSmrg __try
6591debfc3dSmrg {
6601debfc3dSmrg typename _Sp_cd_type::__allocator_type __a2(__a);
6611debfc3dSmrg auto __guard = std::__allocate_guarded(__a2);
6621debfc3dSmrg _Sp_cd_type* __mem = __guard.get();
6631debfc3dSmrg ::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a));
6641debfc3dSmrg _M_pi = __mem;
6651debfc3dSmrg __guard = nullptr;
6661debfc3dSmrg }
6671debfc3dSmrg __catch(...)
6681debfc3dSmrg {
6691debfc3dSmrg __d(__p); // Call _Deleter on __p.
6701debfc3dSmrg __throw_exception_again;
6711debfc3dSmrg }
6721debfc3dSmrg }
6731debfc3dSmrg
6741debfc3dSmrg template<typename _Tp, typename _Alloc, typename... _Args>
675a2dc1f3fSmrg __shared_count(_Tp*& __p, _Sp_alloc_shared_tag<_Alloc> __a,
6761debfc3dSmrg _Args&&... __args)
6771debfc3dSmrg {
6781debfc3dSmrg typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;
679a2dc1f3fSmrg typename _Sp_cp_type::__allocator_type __a2(__a._M_a);
6801debfc3dSmrg auto __guard = std::__allocate_guarded(__a2);
6811debfc3dSmrg _Sp_cp_type* __mem = __guard.get();
682a2dc1f3fSmrg auto __pi = ::new (__mem)
683a2dc1f3fSmrg _Sp_cp_type(__a._M_a, std::forward<_Args>(__args)...);
6841debfc3dSmrg __guard = nullptr;
685a2dc1f3fSmrg _M_pi = __pi;
686a2dc1f3fSmrg __p = __pi->_M_ptr();
6871debfc3dSmrg }
6881debfc3dSmrg
6891debfc3dSmrg #if _GLIBCXX_USE_DEPRECATED
690a2dc1f3fSmrg #pragma GCC diagnostic push
691a2dc1f3fSmrg #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
6921debfc3dSmrg // Special case for auto_ptr<_Tp> to provide the strong guarantee.
6931debfc3dSmrg template<typename _Tp>
6941debfc3dSmrg explicit
6951debfc3dSmrg __shared_count(std::auto_ptr<_Tp>&& __r);
696a2dc1f3fSmrg #pragma GCC diagnostic pop
6971debfc3dSmrg #endif
6981debfc3dSmrg
6991debfc3dSmrg // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee.
7001debfc3dSmrg template<typename _Tp, typename _Del>
7011debfc3dSmrg explicit
7021debfc3dSmrg __shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0)
7031debfc3dSmrg {
7041debfc3dSmrg // _GLIBCXX_RESOLVE_LIB_DEFECTS
7051debfc3dSmrg // 2415. Inconsistency between unique_ptr and shared_ptr
7061debfc3dSmrg if (__r.get() == nullptr)
7071debfc3dSmrg return;
7081debfc3dSmrg
7091debfc3dSmrg using _Ptr = typename unique_ptr<_Tp, _Del>::pointer;
7101debfc3dSmrg using _Del2 = typename conditional<is_reference<_Del>::value,
7111debfc3dSmrg reference_wrapper<typename remove_reference<_Del>::type>,
7121debfc3dSmrg _Del>::type;
7131debfc3dSmrg using _Sp_cd_type
7141debfc3dSmrg = _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>;
7151debfc3dSmrg using _Alloc = allocator<_Sp_cd_type>;
7161debfc3dSmrg using _Alloc_traits = allocator_traits<_Alloc>;
7171debfc3dSmrg _Alloc __a;
7181debfc3dSmrg _Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1);
7198feb0f0bSmrg // _GLIBCXX_RESOLVE_LIB_DEFECTS
7208feb0f0bSmrg // 3548. shared_ptr construction from unique_ptr should move
7218feb0f0bSmrg // (not copy) the deleter
7221debfc3dSmrg _Alloc_traits::construct(__a, __mem, __r.release(),
7238feb0f0bSmrg std::forward<_Del>(__r.get_deleter()));
7241debfc3dSmrg _M_pi = __mem;
7251debfc3dSmrg }
7261debfc3dSmrg
7271debfc3dSmrg // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
7281debfc3dSmrg explicit __shared_count(const __weak_count<_Lp>& __r);
7291debfc3dSmrg
7301debfc3dSmrg // Does not throw if __r._M_get_use_count() == 0, caller must check.
7311debfc3dSmrg explicit __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t);
7321debfc3dSmrg
7331debfc3dSmrg ~__shared_count() noexcept
7341debfc3dSmrg {
7351debfc3dSmrg if (_M_pi != nullptr)
7361debfc3dSmrg _M_pi->_M_release();
7371debfc3dSmrg }
7381debfc3dSmrg
7391debfc3dSmrg __shared_count(const __shared_count& __r) noexcept
7401debfc3dSmrg : _M_pi(__r._M_pi)
7411debfc3dSmrg {
7421debfc3dSmrg if (_M_pi != 0)
7431debfc3dSmrg _M_pi->_M_add_ref_copy();
7441debfc3dSmrg }
7451debfc3dSmrg
7461debfc3dSmrg __shared_count&
7471debfc3dSmrg operator=(const __shared_count& __r) noexcept
7481debfc3dSmrg {
7491debfc3dSmrg _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
7501debfc3dSmrg if (__tmp != _M_pi)
7511debfc3dSmrg {
7521debfc3dSmrg if (__tmp != 0)
7531debfc3dSmrg __tmp->_M_add_ref_copy();
7541debfc3dSmrg if (_M_pi != 0)
7551debfc3dSmrg _M_pi->_M_release();
7561debfc3dSmrg _M_pi = __tmp;
7571debfc3dSmrg }
7581debfc3dSmrg return *this;
7591debfc3dSmrg }
7601debfc3dSmrg
7611debfc3dSmrg void
7621debfc3dSmrg _M_swap(__shared_count& __r) noexcept
7631debfc3dSmrg {
7641debfc3dSmrg _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
7651debfc3dSmrg __r._M_pi = _M_pi;
7661debfc3dSmrg _M_pi = __tmp;
7671debfc3dSmrg }
7681debfc3dSmrg
7691debfc3dSmrg long
7701debfc3dSmrg _M_get_use_count() const noexcept
7711debfc3dSmrg { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
7721debfc3dSmrg
7731debfc3dSmrg bool
7741debfc3dSmrg _M_unique() const noexcept
7751debfc3dSmrg { return this->_M_get_use_count() == 1; }
7761debfc3dSmrg
7771debfc3dSmrg void*
7781debfc3dSmrg _M_get_deleter(const std::type_info& __ti) const noexcept
7791debfc3dSmrg { return _M_pi ? _M_pi->_M_get_deleter(__ti) : nullptr; }
7801debfc3dSmrg
7811debfc3dSmrg bool
7821debfc3dSmrg _M_less(const __shared_count& __rhs) const noexcept
7831debfc3dSmrg { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
7841debfc3dSmrg
7851debfc3dSmrg bool
7861debfc3dSmrg _M_less(const __weak_count<_Lp>& __rhs) const noexcept
7871debfc3dSmrg { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
7881debfc3dSmrg
7891debfc3dSmrg // Friend function injected into enclosing namespace and found by ADL
7901debfc3dSmrg friend inline bool
7911debfc3dSmrg operator==(const __shared_count& __a, const __shared_count& __b) noexcept
7921debfc3dSmrg { return __a._M_pi == __b._M_pi; }
7931debfc3dSmrg
7941debfc3dSmrg private:
7951debfc3dSmrg friend class __weak_count<_Lp>;
7961debfc3dSmrg
7971debfc3dSmrg _Sp_counted_base<_Lp>* _M_pi;
7981debfc3dSmrg };
7991debfc3dSmrg
8001debfc3dSmrg
8011debfc3dSmrg template<_Lock_policy _Lp>
8021debfc3dSmrg class __weak_count
8031debfc3dSmrg {
8041debfc3dSmrg public:
8051debfc3dSmrg constexpr __weak_count() noexcept : _M_pi(nullptr)
8061debfc3dSmrg { }
8071debfc3dSmrg
8081debfc3dSmrg __weak_count(const __shared_count<_Lp>& __r) noexcept
8091debfc3dSmrg : _M_pi(__r._M_pi)
8101debfc3dSmrg {
8111debfc3dSmrg if (_M_pi != nullptr)
8121debfc3dSmrg _M_pi->_M_weak_add_ref();
8131debfc3dSmrg }
8141debfc3dSmrg
8151debfc3dSmrg __weak_count(const __weak_count& __r) noexcept
8161debfc3dSmrg : _M_pi(__r._M_pi)
8171debfc3dSmrg {
8181debfc3dSmrg if (_M_pi != nullptr)
8191debfc3dSmrg _M_pi->_M_weak_add_ref();
8201debfc3dSmrg }
8211debfc3dSmrg
8221debfc3dSmrg __weak_count(__weak_count&& __r) noexcept
8231debfc3dSmrg : _M_pi(__r._M_pi)
8241debfc3dSmrg { __r._M_pi = nullptr; }
8251debfc3dSmrg
8261debfc3dSmrg ~__weak_count() noexcept
8271debfc3dSmrg {
8281debfc3dSmrg if (_M_pi != nullptr)
8291debfc3dSmrg _M_pi->_M_weak_release();
8301debfc3dSmrg }
8311debfc3dSmrg
8321debfc3dSmrg __weak_count&
8331debfc3dSmrg operator=(const __shared_count<_Lp>& __r) noexcept
8341debfc3dSmrg {
8351debfc3dSmrg _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
8361debfc3dSmrg if (__tmp != nullptr)
8371debfc3dSmrg __tmp->_M_weak_add_ref();
8381debfc3dSmrg if (_M_pi != nullptr)
8391debfc3dSmrg _M_pi->_M_weak_release();
8401debfc3dSmrg _M_pi = __tmp;
8411debfc3dSmrg return *this;
8421debfc3dSmrg }
8431debfc3dSmrg
8441debfc3dSmrg __weak_count&
8451debfc3dSmrg operator=(const __weak_count& __r) noexcept
8461debfc3dSmrg {
8471debfc3dSmrg _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
8481debfc3dSmrg if (__tmp != nullptr)
8491debfc3dSmrg __tmp->_M_weak_add_ref();
8501debfc3dSmrg if (_M_pi != nullptr)
8511debfc3dSmrg _M_pi->_M_weak_release();
8521debfc3dSmrg _M_pi = __tmp;
8531debfc3dSmrg return *this;
8541debfc3dSmrg }
8551debfc3dSmrg
8561debfc3dSmrg __weak_count&
8571debfc3dSmrg operator=(__weak_count&& __r) noexcept
8581debfc3dSmrg {
8591debfc3dSmrg if (_M_pi != nullptr)
8601debfc3dSmrg _M_pi->_M_weak_release();
8611debfc3dSmrg _M_pi = __r._M_pi;
8621debfc3dSmrg __r._M_pi = nullptr;
8631debfc3dSmrg return *this;
8641debfc3dSmrg }
8651debfc3dSmrg
8661debfc3dSmrg void
8671debfc3dSmrg _M_swap(__weak_count& __r) noexcept
8681debfc3dSmrg {
8691debfc3dSmrg _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
8701debfc3dSmrg __r._M_pi = _M_pi;
8711debfc3dSmrg _M_pi = __tmp;
8721debfc3dSmrg }
8731debfc3dSmrg
8741debfc3dSmrg long
8751debfc3dSmrg _M_get_use_count() const noexcept
8761debfc3dSmrg { return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; }
8771debfc3dSmrg
8781debfc3dSmrg bool
8791debfc3dSmrg _M_less(const __weak_count& __rhs) const noexcept
8801debfc3dSmrg { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
8811debfc3dSmrg
8821debfc3dSmrg bool
8831debfc3dSmrg _M_less(const __shared_count<_Lp>& __rhs) const noexcept
8841debfc3dSmrg { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
8851debfc3dSmrg
8861debfc3dSmrg // Friend function injected into enclosing namespace and found by ADL
8871debfc3dSmrg friend inline bool
8881debfc3dSmrg operator==(const __weak_count& __a, const __weak_count& __b) noexcept
8891debfc3dSmrg { return __a._M_pi == __b._M_pi; }
8901debfc3dSmrg
8911debfc3dSmrg private:
8921debfc3dSmrg friend class __shared_count<_Lp>;
8931debfc3dSmrg
8941debfc3dSmrg _Sp_counted_base<_Lp>* _M_pi;
8951debfc3dSmrg };
8961debfc3dSmrg
8971debfc3dSmrg // Now that __weak_count is defined we can define this constructor:
8981debfc3dSmrg template<_Lock_policy _Lp>
8991debfc3dSmrg inline
9001debfc3dSmrg __shared_count<_Lp>::__shared_count(const __weak_count<_Lp>& __r)
9011debfc3dSmrg : _M_pi(__r._M_pi)
9021debfc3dSmrg {
9031debfc3dSmrg if (_M_pi != nullptr)
9041debfc3dSmrg _M_pi->_M_add_ref_lock();
9051debfc3dSmrg else
9061debfc3dSmrg __throw_bad_weak_ptr();
9071debfc3dSmrg }
9081debfc3dSmrg
9091debfc3dSmrg // Now that __weak_count is defined we can define this constructor:
9101debfc3dSmrg template<_Lock_policy _Lp>
9111debfc3dSmrg inline
9121debfc3dSmrg __shared_count<_Lp>::
9131debfc3dSmrg __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t)
9141debfc3dSmrg : _M_pi(__r._M_pi)
9151debfc3dSmrg {
9161debfc3dSmrg if (_M_pi != nullptr)
9171debfc3dSmrg if (!_M_pi->_M_add_ref_lock_nothrow())
9181debfc3dSmrg _M_pi = nullptr;
9191debfc3dSmrg }
9201debfc3dSmrg
921c0a68be4Smrg #define __cpp_lib_shared_ptr_arrays 201611L
9221debfc3dSmrg
9231debfc3dSmrg // Helper traits for shared_ptr of array:
9241debfc3dSmrg
9251debfc3dSmrg // A pointer type Y* is said to be compatible with a pointer type T* when
9261debfc3dSmrg // either Y* is convertible to T* or Y is U[N] and T is U cv [].
9271debfc3dSmrg template<typename _Yp_ptr, typename _Tp_ptr>
9281debfc3dSmrg struct __sp_compatible_with
9291debfc3dSmrg : false_type
9301debfc3dSmrg { };
9311debfc3dSmrg
9321debfc3dSmrg template<typename _Yp, typename _Tp>
9331debfc3dSmrg struct __sp_compatible_with<_Yp*, _Tp*>
9341debfc3dSmrg : is_convertible<_Yp*, _Tp*>::type
9351debfc3dSmrg { };
9361debfc3dSmrg
9371debfc3dSmrg template<typename _Up, size_t _Nm>
9381debfc3dSmrg struct __sp_compatible_with<_Up(*)[_Nm], _Up(*)[]>
9391debfc3dSmrg : true_type
9401debfc3dSmrg { };
9411debfc3dSmrg
9421debfc3dSmrg template<typename _Up, size_t _Nm>
9431debfc3dSmrg struct __sp_compatible_with<_Up(*)[_Nm], const _Up(*)[]>
9441debfc3dSmrg : true_type
9451debfc3dSmrg { };
9461debfc3dSmrg
9471debfc3dSmrg template<typename _Up, size_t _Nm>
9481debfc3dSmrg struct __sp_compatible_with<_Up(*)[_Nm], volatile _Up(*)[]>
9491debfc3dSmrg : true_type
9501debfc3dSmrg { };
9511debfc3dSmrg
9521debfc3dSmrg template<typename _Up, size_t _Nm>
9531debfc3dSmrg struct __sp_compatible_with<_Up(*)[_Nm], const volatile _Up(*)[]>
9541debfc3dSmrg : true_type
9551debfc3dSmrg { };
9561debfc3dSmrg
9571debfc3dSmrg // Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N].
9581debfc3dSmrg template<typename _Up, size_t _Nm, typename _Yp, typename = void>
9591debfc3dSmrg struct __sp_is_constructible_arrN
9601debfc3dSmrg : false_type
9611debfc3dSmrg { };
9621debfc3dSmrg
9631debfc3dSmrg template<typename _Up, size_t _Nm, typename _Yp>
9641debfc3dSmrg struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>>
9651debfc3dSmrg : is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type
9661debfc3dSmrg { };
9671debfc3dSmrg
9681debfc3dSmrg // Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[].
9691debfc3dSmrg template<typename _Up, typename _Yp, typename = void>
9701debfc3dSmrg struct __sp_is_constructible_arr
9711debfc3dSmrg : false_type
9721debfc3dSmrg { };
9731debfc3dSmrg
9741debfc3dSmrg template<typename _Up, typename _Yp>
9751debfc3dSmrg struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>>
9761debfc3dSmrg : is_convertible<_Yp(*)[], _Up(*)[]>::type
9771debfc3dSmrg { };
9781debfc3dSmrg
9791debfc3dSmrg // Trait to check if shared_ptr<T> can be constructed from Y*.
9801debfc3dSmrg template<typename _Tp, typename _Yp>
9811debfc3dSmrg struct __sp_is_constructible;
9821debfc3dSmrg
9831debfc3dSmrg // When T is U[N], Y(*)[N] shall be convertible to T*;
9841debfc3dSmrg template<typename _Up, size_t _Nm, typename _Yp>
9851debfc3dSmrg struct __sp_is_constructible<_Up[_Nm], _Yp>
9861debfc3dSmrg : __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type
9871debfc3dSmrg { };
9881debfc3dSmrg
9891debfc3dSmrg // when T is U[], Y(*)[] shall be convertible to T*;
9901debfc3dSmrg template<typename _Up, typename _Yp>
9911debfc3dSmrg struct __sp_is_constructible<_Up[], _Yp>
9921debfc3dSmrg : __sp_is_constructible_arr<_Up, _Yp>::type
9931debfc3dSmrg { };
9941debfc3dSmrg
9951debfc3dSmrg // otherwise, Y* shall be convertible to T*.
9961debfc3dSmrg template<typename _Tp, typename _Yp>
9971debfc3dSmrg struct __sp_is_constructible
9981debfc3dSmrg : is_convertible<_Yp*, _Tp*>::type
9991debfc3dSmrg { };
10001debfc3dSmrg
10011debfc3dSmrg
10021debfc3dSmrg // Define operator* and operator-> for shared_ptr<T>.
10031debfc3dSmrg template<typename _Tp, _Lock_policy _Lp,
10041debfc3dSmrg bool = is_array<_Tp>::value, bool = is_void<_Tp>::value>
10051debfc3dSmrg class __shared_ptr_access
10061debfc3dSmrg {
10071debfc3dSmrg public:
10081debfc3dSmrg using element_type = _Tp;
10091debfc3dSmrg
10101debfc3dSmrg element_type&
10111debfc3dSmrg operator*() const noexcept
10121debfc3dSmrg {
10131debfc3dSmrg __glibcxx_assert(_M_get() != nullptr);
10141debfc3dSmrg return *_M_get();
10151debfc3dSmrg }
10161debfc3dSmrg
10171debfc3dSmrg element_type*
10181debfc3dSmrg operator->() const noexcept
10191debfc3dSmrg {
10201debfc3dSmrg _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
10211debfc3dSmrg return _M_get();
10221debfc3dSmrg }
10231debfc3dSmrg
10241debfc3dSmrg private:
10251debfc3dSmrg element_type*
10261debfc3dSmrg _M_get() const noexcept
10271debfc3dSmrg { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }
10281debfc3dSmrg };
10291debfc3dSmrg
10301debfc3dSmrg // Define operator-> for shared_ptr<cv void>.
10311debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
10321debfc3dSmrg class __shared_ptr_access<_Tp, _Lp, false, true>
10331debfc3dSmrg {
10341debfc3dSmrg public:
10351debfc3dSmrg using element_type = _Tp;
10361debfc3dSmrg
10371debfc3dSmrg element_type*
10381debfc3dSmrg operator->() const noexcept
10391debfc3dSmrg {
10401debfc3dSmrg auto __ptr = static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get();
10411debfc3dSmrg _GLIBCXX_DEBUG_PEDASSERT(__ptr != nullptr);
10421debfc3dSmrg return __ptr;
10431debfc3dSmrg }
10441debfc3dSmrg };
10451debfc3dSmrg
10461debfc3dSmrg // Define operator[] for shared_ptr<T[]> and shared_ptr<T[N]>.
10471debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
10481debfc3dSmrg class __shared_ptr_access<_Tp, _Lp, true, false>
10491debfc3dSmrg {
10501debfc3dSmrg public:
10511debfc3dSmrg using element_type = typename remove_extent<_Tp>::type;
10521debfc3dSmrg
10531debfc3dSmrg #if __cplusplus <= 201402L
10541debfc3dSmrg [[__deprecated__("shared_ptr<T[]>::operator* is absent from C++17")]]
10551debfc3dSmrg element_type&
10561debfc3dSmrg operator*() const noexcept
10571debfc3dSmrg {
10581debfc3dSmrg __glibcxx_assert(_M_get() != nullptr);
10591debfc3dSmrg return *_M_get();
10601debfc3dSmrg }
10611debfc3dSmrg
10621debfc3dSmrg [[__deprecated__("shared_ptr<T[]>::operator-> is absent from C++17")]]
10631debfc3dSmrg element_type*
10641debfc3dSmrg operator->() const noexcept
10651debfc3dSmrg {
10661debfc3dSmrg _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
10671debfc3dSmrg return _M_get();
10681debfc3dSmrg }
10691debfc3dSmrg #endif
10701debfc3dSmrg
10711debfc3dSmrg element_type&
10721debfc3dSmrg operator[](ptrdiff_t __i) const
10731debfc3dSmrg {
10741debfc3dSmrg __glibcxx_assert(_M_get() != nullptr);
10751debfc3dSmrg __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value);
10761debfc3dSmrg return _M_get()[__i];
10771debfc3dSmrg }
10781debfc3dSmrg
10791debfc3dSmrg private:
10801debfc3dSmrg element_type*
10811debfc3dSmrg _M_get() const noexcept
10821debfc3dSmrg { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }
10831debfc3dSmrg };
10841debfc3dSmrg
10851debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
10861debfc3dSmrg class __shared_ptr
10871debfc3dSmrg : public __shared_ptr_access<_Tp, _Lp>
10881debfc3dSmrg {
10891debfc3dSmrg public:
10901debfc3dSmrg using element_type = typename remove_extent<_Tp>::type;
10911debfc3dSmrg
10921debfc3dSmrg private:
10931debfc3dSmrg // Constraint for taking ownership of a pointer of type _Yp*:
10941debfc3dSmrg template<typename _Yp>
10951debfc3dSmrg using _SafeConv
10961debfc3dSmrg = typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type;
10971debfc3dSmrg
10981debfc3dSmrg // Constraint for construction from shared_ptr and weak_ptr:
10991debfc3dSmrg template<typename _Yp, typename _Res = void>
11001debfc3dSmrg using _Compatible = typename
11011debfc3dSmrg enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
11021debfc3dSmrg
11031debfc3dSmrg // Constraint for assignment from shared_ptr and weak_ptr:
11041debfc3dSmrg template<typename _Yp>
11051debfc3dSmrg using _Assignable = _Compatible<_Yp, __shared_ptr&>;
11061debfc3dSmrg
11071debfc3dSmrg // Constraint for construction from unique_ptr:
11081debfc3dSmrg template<typename _Yp, typename _Del, typename _Res = void,
11091debfc3dSmrg typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer>
11108feb0f0bSmrg using _UniqCompatible = __enable_if_t<__and_<
11118feb0f0bSmrg __sp_compatible_with<_Yp*, _Tp*>,
11128feb0f0bSmrg is_convertible<_Ptr, element_type*>,
11138feb0f0bSmrg is_move_constructible<_Del>
11148feb0f0bSmrg >::value, _Res>;
11151debfc3dSmrg
11161debfc3dSmrg // Constraint for assignment from unique_ptr:
11171debfc3dSmrg template<typename _Yp, typename _Del>
11181debfc3dSmrg using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>;
11191debfc3dSmrg
11201debfc3dSmrg public:
11211debfc3dSmrg
11221debfc3dSmrg #if __cplusplus > 201402L
11231debfc3dSmrg using weak_type = __weak_ptr<_Tp, _Lp>;
11241debfc3dSmrg #endif
11251debfc3dSmrg
11261debfc3dSmrg constexpr __shared_ptr() noexcept
11271debfc3dSmrg : _M_ptr(0), _M_refcount()
11281debfc3dSmrg { }
11291debfc3dSmrg
11301debfc3dSmrg template<typename _Yp, typename = _SafeConv<_Yp>>
11311debfc3dSmrg explicit
11321debfc3dSmrg __shared_ptr(_Yp* __p)
11331debfc3dSmrg : _M_ptr(__p), _M_refcount(__p, typename is_array<_Tp>::type())
11341debfc3dSmrg {
11351debfc3dSmrg static_assert( !is_void<_Yp>::value, "incomplete type" );
11361debfc3dSmrg static_assert( sizeof(_Yp) > 0, "incomplete type" );
11371debfc3dSmrg _M_enable_shared_from_this_with(__p);
11381debfc3dSmrg }
11391debfc3dSmrg
11401debfc3dSmrg template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>>
11411debfc3dSmrg __shared_ptr(_Yp* __p, _Deleter __d)
11421debfc3dSmrg : _M_ptr(__p), _M_refcount(__p, std::move(__d))
11431debfc3dSmrg {
11441debfc3dSmrg static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
11451debfc3dSmrg "deleter expression d(p) is well-formed");
11461debfc3dSmrg _M_enable_shared_from_this_with(__p);
11471debfc3dSmrg }
11481debfc3dSmrg
11491debfc3dSmrg template<typename _Yp, typename _Deleter, typename _Alloc,
11501debfc3dSmrg typename = _SafeConv<_Yp>>
11511debfc3dSmrg __shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
11521debfc3dSmrg : _M_ptr(__p), _M_refcount(__p, std::move(__d), std::move(__a))
11531debfc3dSmrg {
11541debfc3dSmrg static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
11551debfc3dSmrg "deleter expression d(p) is well-formed");
11561debfc3dSmrg _M_enable_shared_from_this_with(__p);
11571debfc3dSmrg }
11581debfc3dSmrg
11591debfc3dSmrg template<typename _Deleter>
11601debfc3dSmrg __shared_ptr(nullptr_t __p, _Deleter __d)
11611debfc3dSmrg : _M_ptr(0), _M_refcount(__p, std::move(__d))
11621debfc3dSmrg { }
11631debfc3dSmrg
11641debfc3dSmrg template<typename _Deleter, typename _Alloc>
11651debfc3dSmrg __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
11661debfc3dSmrg : _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a))
11671debfc3dSmrg { }
11681debfc3dSmrg
11698feb0f0bSmrg // Aliasing constructor
11701debfc3dSmrg template<typename _Yp>
11711debfc3dSmrg __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r,
11721debfc3dSmrg element_type* __p) noexcept
11731debfc3dSmrg : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
11741debfc3dSmrg { }
11751debfc3dSmrg
11768feb0f0bSmrg // Aliasing constructor
11778feb0f0bSmrg template<typename _Yp>
11788feb0f0bSmrg __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r,
11798feb0f0bSmrg element_type* __p) noexcept
11808feb0f0bSmrg : _M_ptr(__p), _M_refcount()
11818feb0f0bSmrg {
11828feb0f0bSmrg _M_refcount._M_swap(__r._M_refcount);
11838feb0f0bSmrg __r._M_ptr = 0;
11848feb0f0bSmrg }
11858feb0f0bSmrg
11861debfc3dSmrg __shared_ptr(const __shared_ptr&) noexcept = default;
11871debfc3dSmrg __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
11881debfc3dSmrg ~__shared_ptr() = default;
11891debfc3dSmrg
11901debfc3dSmrg template<typename _Yp, typename = _Compatible<_Yp>>
11911debfc3dSmrg __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
11921debfc3dSmrg : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
11931debfc3dSmrg { }
11941debfc3dSmrg
11951debfc3dSmrg __shared_ptr(__shared_ptr&& __r) noexcept
11961debfc3dSmrg : _M_ptr(__r._M_ptr), _M_refcount()
11971debfc3dSmrg {
11981debfc3dSmrg _M_refcount._M_swap(__r._M_refcount);
11991debfc3dSmrg __r._M_ptr = 0;
12001debfc3dSmrg }
12011debfc3dSmrg
12021debfc3dSmrg template<typename _Yp, typename = _Compatible<_Yp>>
12031debfc3dSmrg __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept
12041debfc3dSmrg : _M_ptr(__r._M_ptr), _M_refcount()
12051debfc3dSmrg {
12061debfc3dSmrg _M_refcount._M_swap(__r._M_refcount);
12071debfc3dSmrg __r._M_ptr = 0;
12081debfc3dSmrg }
12091debfc3dSmrg
12101debfc3dSmrg template<typename _Yp, typename = _Compatible<_Yp>>
12111debfc3dSmrg explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r)
12121debfc3dSmrg : _M_refcount(__r._M_refcount) // may throw
12131debfc3dSmrg {
12141debfc3dSmrg // It is now safe to copy __r._M_ptr, as
12151debfc3dSmrg // _M_refcount(__r._M_refcount) did not throw.
12161debfc3dSmrg _M_ptr = __r._M_ptr;
12171debfc3dSmrg }
12181debfc3dSmrg
12191debfc3dSmrg // If an exception is thrown this constructor has no effect.
12201debfc3dSmrg template<typename _Yp, typename _Del,
12211debfc3dSmrg typename = _UniqCompatible<_Yp, _Del>>
12221debfc3dSmrg __shared_ptr(unique_ptr<_Yp, _Del>&& __r)
12231debfc3dSmrg : _M_ptr(__r.get()), _M_refcount()
12241debfc3dSmrg {
1225a2dc1f3fSmrg auto __raw = __to_address(__r.get());
12261debfc3dSmrg _M_refcount = __shared_count<_Lp>(std::move(__r));
12271debfc3dSmrg _M_enable_shared_from_this_with(__raw);
12281debfc3dSmrg }
12291debfc3dSmrg
12301debfc3dSmrg #if __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATED
12311debfc3dSmrg protected:
12321debfc3dSmrg // If an exception is thrown this constructor has no effect.
12331debfc3dSmrg template<typename _Tp1, typename _Del,
12341debfc3dSmrg typename enable_if<__and_<
12351debfc3dSmrg __not_<is_array<_Tp>>, is_array<_Tp1>,
12361debfc3dSmrg is_convertible<typename unique_ptr<_Tp1, _Del>::pointer, _Tp*>
12371debfc3dSmrg >::value, bool>::type = true>
12381debfc3dSmrg __shared_ptr(unique_ptr<_Tp1, _Del>&& __r, __sp_array_delete)
12391debfc3dSmrg : _M_ptr(__r.get()), _M_refcount()
12401debfc3dSmrg {
1241a2dc1f3fSmrg auto __raw = __to_address(__r.get());
12421debfc3dSmrg _M_refcount = __shared_count<_Lp>(std::move(__r));
12431debfc3dSmrg _M_enable_shared_from_this_with(__raw);
12441debfc3dSmrg }
12451debfc3dSmrg public:
12461debfc3dSmrg #endif
12471debfc3dSmrg
12481debfc3dSmrg #if _GLIBCXX_USE_DEPRECATED
1249a2dc1f3fSmrg #pragma GCC diagnostic push
1250a2dc1f3fSmrg #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
12511debfc3dSmrg // Postcondition: use_count() == 1 and __r.get() == 0
12521debfc3dSmrg template<typename _Yp, typename = _Compatible<_Yp>>
12531debfc3dSmrg __shared_ptr(auto_ptr<_Yp>&& __r);
1254a2dc1f3fSmrg #pragma GCC diagnostic pop
12551debfc3dSmrg #endif
12561debfc3dSmrg
12571debfc3dSmrg constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
12581debfc3dSmrg
12591debfc3dSmrg template<typename _Yp>
12601debfc3dSmrg _Assignable<_Yp>
12611debfc3dSmrg operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
12621debfc3dSmrg {
12631debfc3dSmrg _M_ptr = __r._M_ptr;
12641debfc3dSmrg _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
12651debfc3dSmrg return *this;
12661debfc3dSmrg }
12671debfc3dSmrg
12681debfc3dSmrg #if _GLIBCXX_USE_DEPRECATED
1269a2dc1f3fSmrg #pragma GCC diagnostic push
1270a2dc1f3fSmrg #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
12711debfc3dSmrg template<typename _Yp>
12721debfc3dSmrg _Assignable<_Yp>
12731debfc3dSmrg operator=(auto_ptr<_Yp>&& __r)
12741debfc3dSmrg {
12751debfc3dSmrg __shared_ptr(std::move(__r)).swap(*this);
12761debfc3dSmrg return *this;
12771debfc3dSmrg }
1278a2dc1f3fSmrg #pragma GCC diagnostic pop
12791debfc3dSmrg #endif
12801debfc3dSmrg
12811debfc3dSmrg __shared_ptr&
12821debfc3dSmrg operator=(__shared_ptr&& __r) noexcept
12831debfc3dSmrg {
12841debfc3dSmrg __shared_ptr(std::move(__r)).swap(*this);
12851debfc3dSmrg return *this;
12861debfc3dSmrg }
12871debfc3dSmrg
12881debfc3dSmrg template<class _Yp>
12891debfc3dSmrg _Assignable<_Yp>
12901debfc3dSmrg operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept
12911debfc3dSmrg {
12921debfc3dSmrg __shared_ptr(std::move(__r)).swap(*this);
12931debfc3dSmrg return *this;
12941debfc3dSmrg }
12951debfc3dSmrg
12961debfc3dSmrg template<typename _Yp, typename _Del>
12971debfc3dSmrg _UniqAssignable<_Yp, _Del>
12981debfc3dSmrg operator=(unique_ptr<_Yp, _Del>&& __r)
12991debfc3dSmrg {
13001debfc3dSmrg __shared_ptr(std::move(__r)).swap(*this);
13011debfc3dSmrg return *this;
13021debfc3dSmrg }
13031debfc3dSmrg
13041debfc3dSmrg void
13051debfc3dSmrg reset() noexcept
13061debfc3dSmrg { __shared_ptr().swap(*this); }
13071debfc3dSmrg
13081debfc3dSmrg template<typename _Yp>
13091debfc3dSmrg _SafeConv<_Yp>
13101debfc3dSmrg reset(_Yp* __p) // _Yp must be complete.
13111debfc3dSmrg {
13121debfc3dSmrg // Catch self-reset errors.
13131debfc3dSmrg __glibcxx_assert(__p == 0 || __p != _M_ptr);
13141debfc3dSmrg __shared_ptr(__p).swap(*this);
13151debfc3dSmrg }
13161debfc3dSmrg
13171debfc3dSmrg template<typename _Yp, typename _Deleter>
13181debfc3dSmrg _SafeConv<_Yp>
13191debfc3dSmrg reset(_Yp* __p, _Deleter __d)
13201debfc3dSmrg { __shared_ptr(__p, std::move(__d)).swap(*this); }
13211debfc3dSmrg
13221debfc3dSmrg template<typename _Yp, typename _Deleter, typename _Alloc>
13231debfc3dSmrg _SafeConv<_Yp>
13241debfc3dSmrg reset(_Yp* __p, _Deleter __d, _Alloc __a)
13251debfc3dSmrg { __shared_ptr(__p, std::move(__d), std::move(__a)).swap(*this); }
13261debfc3dSmrg
13278feb0f0bSmrg /// Return the stored pointer.
13281debfc3dSmrg element_type*
13291debfc3dSmrg get() const noexcept
13301debfc3dSmrg { return _M_ptr; }
13311debfc3dSmrg
13328feb0f0bSmrg /// Return true if the stored pointer is not null.
13331debfc3dSmrg explicit operator bool() const // never throws
13341debfc3dSmrg { return _M_ptr == 0 ? false : true; }
13351debfc3dSmrg
13368feb0f0bSmrg /// Return true if use_count() == 1.
13371debfc3dSmrg bool
13381debfc3dSmrg unique() const noexcept
13391debfc3dSmrg { return _M_refcount._M_unique(); }
13401debfc3dSmrg
13418feb0f0bSmrg /// If *this owns a pointer, return the number of owners, otherwise zero.
13421debfc3dSmrg long
13431debfc3dSmrg use_count() const noexcept
13441debfc3dSmrg { return _M_refcount._M_get_use_count(); }
13451debfc3dSmrg
13468feb0f0bSmrg /// Exchange both the owned pointer and the stored pointer.
13471debfc3dSmrg void
13481debfc3dSmrg swap(__shared_ptr<_Tp, _Lp>& __other) noexcept
13491debfc3dSmrg {
13501debfc3dSmrg std::swap(_M_ptr, __other._M_ptr);
13511debfc3dSmrg _M_refcount._M_swap(__other._M_refcount);
13521debfc3dSmrg }
13531debfc3dSmrg
13548feb0f0bSmrg /** @brief Define an ordering based on ownership.
13558feb0f0bSmrg *
13568feb0f0bSmrg * This function defines a strict weak ordering between two shared_ptr
13578feb0f0bSmrg * or weak_ptr objects, such that one object is less than the other
13588feb0f0bSmrg * unless they share ownership of the same pointer, or are both empty.
13598feb0f0bSmrg * @{
13608feb0f0bSmrg */
13611debfc3dSmrg template<typename _Tp1>
13621debfc3dSmrg bool
13631debfc3dSmrg owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept
13641debfc3dSmrg { return _M_refcount._M_less(__rhs._M_refcount); }
13651debfc3dSmrg
13661debfc3dSmrg template<typename _Tp1>
13671debfc3dSmrg bool
13681debfc3dSmrg owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept
13691debfc3dSmrg { return _M_refcount._M_less(__rhs._M_refcount); }
13708feb0f0bSmrg /// @}
13711debfc3dSmrg
13721debfc3dSmrg protected:
13731debfc3dSmrg // This constructor is non-standard, it is used by allocate_shared.
13741debfc3dSmrg template<typename _Alloc, typename... _Args>
1375a2dc1f3fSmrg __shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
1376a2dc1f3fSmrg : _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...)
1377a2dc1f3fSmrg { _M_enable_shared_from_this_with(_M_ptr); }
13781debfc3dSmrg
13791debfc3dSmrg template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc,
13801debfc3dSmrg typename... _Args>
13811debfc3dSmrg friend __shared_ptr<_Tp1, _Lp1>
13821debfc3dSmrg __allocate_shared(const _Alloc& __a, _Args&&... __args);
13831debfc3dSmrg
13841debfc3dSmrg // This constructor is used by __weak_ptr::lock() and
13851debfc3dSmrg // shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t).
13861debfc3dSmrg __shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t)
13871debfc3dSmrg : _M_refcount(__r._M_refcount, std::nothrow)
13881debfc3dSmrg {
13891debfc3dSmrg _M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr;
13901debfc3dSmrg }
13911debfc3dSmrg
13921debfc3dSmrg friend class __weak_ptr<_Tp, _Lp>;
13931debfc3dSmrg
13941debfc3dSmrg private:
13951debfc3dSmrg
13961debfc3dSmrg template<typename _Yp>
13971debfc3dSmrg using __esft_base_t = decltype(__enable_shared_from_this_base(
13981debfc3dSmrg std::declval<const __shared_count<_Lp>&>(),
13991debfc3dSmrg std::declval<_Yp*>()));
14001debfc3dSmrg
14011debfc3dSmrg // Detect an accessible and unambiguous enable_shared_from_this base.
14021debfc3dSmrg template<typename _Yp, typename = void>
14031debfc3dSmrg struct __has_esft_base
14041debfc3dSmrg : false_type { };
14051debfc3dSmrg
14061debfc3dSmrg template<typename _Yp>
14071debfc3dSmrg struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>>
14081debfc3dSmrg : __not_<is_array<_Tp>> { }; // No enable shared_from_this for arrays
14091debfc3dSmrg
14101debfc3dSmrg template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
14111debfc3dSmrg typename enable_if<__has_esft_base<_Yp2>::value>::type
14121debfc3dSmrg _M_enable_shared_from_this_with(_Yp* __p) noexcept
14131debfc3dSmrg {
14141debfc3dSmrg if (auto __base = __enable_shared_from_this_base(_M_refcount, __p))
14151debfc3dSmrg __base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount);
14161debfc3dSmrg }
14171debfc3dSmrg
14181debfc3dSmrg template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
14191debfc3dSmrg typename enable_if<!__has_esft_base<_Yp2>::value>::type
14201debfc3dSmrg _M_enable_shared_from_this_with(_Yp*) noexcept
14211debfc3dSmrg { }
14221debfc3dSmrg
14231debfc3dSmrg void*
14241debfc3dSmrg _M_get_deleter(const std::type_info& __ti) const noexcept
14251debfc3dSmrg { return _M_refcount._M_get_deleter(__ti); }
14261debfc3dSmrg
14271debfc3dSmrg template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
14281debfc3dSmrg template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
14291debfc3dSmrg
14301debfc3dSmrg template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
14311debfc3dSmrg friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
14321debfc3dSmrg
1433a2dc1f3fSmrg template<typename _Del, typename _Tp1>
1434a2dc1f3fSmrg friend _Del* get_deleter(const shared_ptr<_Tp1>&) noexcept;
1435a2dc1f3fSmrg
14361debfc3dSmrg element_type* _M_ptr; // Contained pointer.
14371debfc3dSmrg __shared_count<_Lp> _M_refcount; // Reference counter.
14381debfc3dSmrg };
14391debfc3dSmrg
14401debfc3dSmrg
14411debfc3dSmrg // 20.7.2.2.7 shared_ptr comparisons
14421debfc3dSmrg template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
14431debfc3dSmrg inline bool
14441debfc3dSmrg operator==(const __shared_ptr<_Tp1, _Lp>& __a,
14451debfc3dSmrg const __shared_ptr<_Tp2, _Lp>& __b) noexcept
14461debfc3dSmrg { return __a.get() == __b.get(); }
14471debfc3dSmrg
14481debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
14491debfc3dSmrg inline bool
14501debfc3dSmrg operator==(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
14511debfc3dSmrg { return !__a; }
14521debfc3dSmrg
14538feb0f0bSmrg #ifdef __cpp_lib_three_way_comparison
14548feb0f0bSmrg template<typename _Tp, typename _Up, _Lock_policy _Lp>
14558feb0f0bSmrg inline strong_ordering
14568feb0f0bSmrg operator<=>(const __shared_ptr<_Tp, _Lp>& __a,
14578feb0f0bSmrg const __shared_ptr<_Up, _Lp>& __b) noexcept
14588feb0f0bSmrg { return compare_three_way()(__a.get(), __b.get()); }
14598feb0f0bSmrg
14608feb0f0bSmrg template<typename _Tp, _Lock_policy _Lp>
14618feb0f0bSmrg inline strong_ordering
14628feb0f0bSmrg operator<=>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
14638feb0f0bSmrg {
14648feb0f0bSmrg using pointer = typename __shared_ptr<_Tp, _Lp>::element_type*;
14658feb0f0bSmrg return compare_three_way()(__a.get(), static_cast<pointer>(nullptr));
14668feb0f0bSmrg }
14678feb0f0bSmrg #else
14681debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
14691debfc3dSmrg inline bool
14701debfc3dSmrg operator==(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
14711debfc3dSmrg { return !__a; }
14721debfc3dSmrg
14731debfc3dSmrg template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
14741debfc3dSmrg inline bool
14751debfc3dSmrg operator!=(const __shared_ptr<_Tp1, _Lp>& __a,
14761debfc3dSmrg const __shared_ptr<_Tp2, _Lp>& __b) noexcept
14771debfc3dSmrg { return __a.get() != __b.get(); }
14781debfc3dSmrg
14791debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
14801debfc3dSmrg inline bool
14811debfc3dSmrg operator!=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
14821debfc3dSmrg { return (bool)__a; }
14831debfc3dSmrg
14841debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
14851debfc3dSmrg inline bool
14861debfc3dSmrg operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
14871debfc3dSmrg { return (bool)__a; }
14881debfc3dSmrg
14891debfc3dSmrg template<typename _Tp, typename _Up, _Lock_policy _Lp>
14901debfc3dSmrg inline bool
14911debfc3dSmrg operator<(const __shared_ptr<_Tp, _Lp>& __a,
14921debfc3dSmrg const __shared_ptr<_Up, _Lp>& __b) noexcept
14931debfc3dSmrg {
14941debfc3dSmrg using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
14951debfc3dSmrg using _Up_elt = typename __shared_ptr<_Up, _Lp>::element_type;
14961debfc3dSmrg using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
14971debfc3dSmrg return less<_Vp>()(__a.get(), __b.get());
14981debfc3dSmrg }
14991debfc3dSmrg
15001debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
15011debfc3dSmrg inline bool
15021debfc3dSmrg operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
15031debfc3dSmrg {
15041debfc3dSmrg using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
15051debfc3dSmrg return less<_Tp_elt*>()(__a.get(), nullptr);
15061debfc3dSmrg }
15071debfc3dSmrg
15081debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
15091debfc3dSmrg inline bool
15101debfc3dSmrg operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
15111debfc3dSmrg {
15121debfc3dSmrg using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
15131debfc3dSmrg return less<_Tp_elt*>()(nullptr, __a.get());
15141debfc3dSmrg }
15151debfc3dSmrg
15161debfc3dSmrg template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
15171debfc3dSmrg inline bool
15181debfc3dSmrg operator<=(const __shared_ptr<_Tp1, _Lp>& __a,
15191debfc3dSmrg const __shared_ptr<_Tp2, _Lp>& __b) noexcept
15201debfc3dSmrg { return !(__b < __a); }
15211debfc3dSmrg
15221debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
15231debfc3dSmrg inline bool
15241debfc3dSmrg operator<=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
15251debfc3dSmrg { return !(nullptr < __a); }
15261debfc3dSmrg
15271debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
15281debfc3dSmrg inline bool
15291debfc3dSmrg operator<=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
15301debfc3dSmrg { return !(__a < nullptr); }
15311debfc3dSmrg
15321debfc3dSmrg template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
15331debfc3dSmrg inline bool
15341debfc3dSmrg operator>(const __shared_ptr<_Tp1, _Lp>& __a,
15351debfc3dSmrg const __shared_ptr<_Tp2, _Lp>& __b) noexcept
15361debfc3dSmrg { return (__b < __a); }
15371debfc3dSmrg
15381debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
15391debfc3dSmrg inline bool
15401debfc3dSmrg operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
15411debfc3dSmrg { return nullptr < __a; }
15421debfc3dSmrg
15431debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
15441debfc3dSmrg inline bool
15451debfc3dSmrg operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
15461debfc3dSmrg { return __a < nullptr; }
15471debfc3dSmrg
15481debfc3dSmrg template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
15491debfc3dSmrg inline bool
15501debfc3dSmrg operator>=(const __shared_ptr<_Tp1, _Lp>& __a,
15511debfc3dSmrg const __shared_ptr<_Tp2, _Lp>& __b) noexcept
15521debfc3dSmrg { return !(__a < __b); }
15531debfc3dSmrg
15541debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
15551debfc3dSmrg inline bool
15561debfc3dSmrg operator>=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
15571debfc3dSmrg { return !(__a < nullptr); }
15581debfc3dSmrg
15591debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
15601debfc3dSmrg inline bool
15611debfc3dSmrg operator>=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
15621debfc3dSmrg { return !(nullptr < __a); }
15638feb0f0bSmrg #endif // three-way comparison
15641debfc3dSmrg
15651debfc3dSmrg // 20.7.2.2.8 shared_ptr specialized algorithms.
15661debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
15671debfc3dSmrg inline void
15681debfc3dSmrg swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) noexcept
15691debfc3dSmrg { __a.swap(__b); }
15701debfc3dSmrg
15711debfc3dSmrg // 20.7.2.2.9 shared_ptr casts
15721debfc3dSmrg
15731debfc3dSmrg // The seemingly equivalent code:
15741debfc3dSmrg // shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))
15751debfc3dSmrg // will eventually result in undefined behaviour, attempting to
15761debfc3dSmrg // delete the same object twice.
15771debfc3dSmrg /// static_pointer_cast
15781debfc3dSmrg template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
15791debfc3dSmrg inline __shared_ptr<_Tp, _Lp>
15801debfc3dSmrg static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
15811debfc3dSmrg {
15821debfc3dSmrg using _Sp = __shared_ptr<_Tp, _Lp>;
15831debfc3dSmrg return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
15841debfc3dSmrg }
15851debfc3dSmrg
15861debfc3dSmrg // The seemingly equivalent code:
15871debfc3dSmrg // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
15881debfc3dSmrg // will eventually result in undefined behaviour, attempting to
15891debfc3dSmrg // delete the same object twice.
15901debfc3dSmrg /// const_pointer_cast
15911debfc3dSmrg template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
15921debfc3dSmrg inline __shared_ptr<_Tp, _Lp>
15931debfc3dSmrg const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
15941debfc3dSmrg {
15951debfc3dSmrg using _Sp = __shared_ptr<_Tp, _Lp>;
15961debfc3dSmrg return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
15971debfc3dSmrg }
15981debfc3dSmrg
15991debfc3dSmrg // The seemingly equivalent code:
16001debfc3dSmrg // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
16011debfc3dSmrg // will eventually result in undefined behaviour, attempting to
16021debfc3dSmrg // delete the same object twice.
16031debfc3dSmrg /// dynamic_pointer_cast
16041debfc3dSmrg template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
16051debfc3dSmrg inline __shared_ptr<_Tp, _Lp>
16061debfc3dSmrg dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
16071debfc3dSmrg {
16081debfc3dSmrg using _Sp = __shared_ptr<_Tp, _Lp>;
16091debfc3dSmrg if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
16101debfc3dSmrg return _Sp(__r, __p);
16111debfc3dSmrg return _Sp();
16121debfc3dSmrg }
16131debfc3dSmrg
16141debfc3dSmrg #if __cplusplus > 201402L
16151debfc3dSmrg template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
16161debfc3dSmrg inline __shared_ptr<_Tp, _Lp>
16171debfc3dSmrg reinterpret_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
16181debfc3dSmrg {
16191debfc3dSmrg using _Sp = __shared_ptr<_Tp, _Lp>;
16201debfc3dSmrg return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
16211debfc3dSmrg }
16221debfc3dSmrg #endif
16231debfc3dSmrg
16241debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
16251debfc3dSmrg class __weak_ptr
16261debfc3dSmrg {
16271debfc3dSmrg template<typename _Yp, typename _Res = void>
16281debfc3dSmrg using _Compatible = typename
16291debfc3dSmrg enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
16301debfc3dSmrg
16311debfc3dSmrg // Constraint for assignment from shared_ptr and weak_ptr:
16321debfc3dSmrg template<typename _Yp>
16331debfc3dSmrg using _Assignable = _Compatible<_Yp, __weak_ptr&>;
16341debfc3dSmrg
16351debfc3dSmrg public:
16361debfc3dSmrg using element_type = typename remove_extent<_Tp>::type;
16371debfc3dSmrg
16381debfc3dSmrg constexpr __weak_ptr() noexcept
16391debfc3dSmrg : _M_ptr(nullptr), _M_refcount()
16401debfc3dSmrg { }
16411debfc3dSmrg
16421debfc3dSmrg __weak_ptr(const __weak_ptr&) noexcept = default;
16431debfc3dSmrg
16441debfc3dSmrg ~__weak_ptr() = default;
16451debfc3dSmrg
16461debfc3dSmrg // The "obvious" converting constructor implementation:
16471debfc3dSmrg //
16481debfc3dSmrg // template<typename _Tp1>
16491debfc3dSmrg // __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
16501debfc3dSmrg // : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
16511debfc3dSmrg // { }
16521debfc3dSmrg //
16531debfc3dSmrg // has a serious problem.
16541debfc3dSmrg //
16551debfc3dSmrg // __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr)
16561debfc3dSmrg // conversion may require access to *__r._M_ptr (virtual inheritance).
16571debfc3dSmrg //
16581debfc3dSmrg // It is not possible to avoid spurious access violations since
16591debfc3dSmrg // in multithreaded programs __r._M_ptr may be invalidated at any point.
16601debfc3dSmrg template<typename _Yp, typename = _Compatible<_Yp>>
16611debfc3dSmrg __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept
16621debfc3dSmrg : _M_refcount(__r._M_refcount)
16631debfc3dSmrg { _M_ptr = __r.lock().get(); }
16641debfc3dSmrg
16651debfc3dSmrg template<typename _Yp, typename = _Compatible<_Yp>>
16661debfc3dSmrg __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
16671debfc3dSmrg : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
16681debfc3dSmrg { }
16691debfc3dSmrg
16701debfc3dSmrg __weak_ptr(__weak_ptr&& __r) noexcept
16711debfc3dSmrg : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount))
16721debfc3dSmrg { __r._M_ptr = nullptr; }
16731debfc3dSmrg
16741debfc3dSmrg template<typename _Yp, typename = _Compatible<_Yp>>
16751debfc3dSmrg __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept
16761debfc3dSmrg : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
16771debfc3dSmrg { __r._M_ptr = nullptr; }
16781debfc3dSmrg
16791debfc3dSmrg __weak_ptr&
16801debfc3dSmrg operator=(const __weak_ptr& __r) noexcept = default;
16811debfc3dSmrg
16821debfc3dSmrg template<typename _Yp>
16831debfc3dSmrg _Assignable<_Yp>
16841debfc3dSmrg operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept
16851debfc3dSmrg {
16861debfc3dSmrg _M_ptr = __r.lock().get();
16871debfc3dSmrg _M_refcount = __r._M_refcount;
16881debfc3dSmrg return *this;
16891debfc3dSmrg }
16901debfc3dSmrg
16911debfc3dSmrg template<typename _Yp>
16921debfc3dSmrg _Assignable<_Yp>
16931debfc3dSmrg operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
16941debfc3dSmrg {
16951debfc3dSmrg _M_ptr = __r._M_ptr;
16961debfc3dSmrg _M_refcount = __r._M_refcount;
16971debfc3dSmrg return *this;
16981debfc3dSmrg }
16991debfc3dSmrg
17001debfc3dSmrg __weak_ptr&
17011debfc3dSmrg operator=(__weak_ptr&& __r) noexcept
17021debfc3dSmrg {
1703*23f5f463Smrg __weak_ptr(std::move(__r)).swap(*this);
17041debfc3dSmrg return *this;
17051debfc3dSmrg }
17061debfc3dSmrg
17071debfc3dSmrg template<typename _Yp>
17081debfc3dSmrg _Assignable<_Yp>
17091debfc3dSmrg operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept
17101debfc3dSmrg {
17111debfc3dSmrg _M_ptr = __r.lock().get();
17121debfc3dSmrg _M_refcount = std::move(__r._M_refcount);
17131debfc3dSmrg __r._M_ptr = nullptr;
17141debfc3dSmrg return *this;
17151debfc3dSmrg }
17161debfc3dSmrg
17171debfc3dSmrg __shared_ptr<_Tp, _Lp>
17181debfc3dSmrg lock() const noexcept
17191debfc3dSmrg { return __shared_ptr<element_type, _Lp>(*this, std::nothrow); }
17201debfc3dSmrg
17211debfc3dSmrg long
17221debfc3dSmrg use_count() const noexcept
17231debfc3dSmrg { return _M_refcount._M_get_use_count(); }
17241debfc3dSmrg
17251debfc3dSmrg bool
17261debfc3dSmrg expired() const noexcept
17271debfc3dSmrg { return _M_refcount._M_get_use_count() == 0; }
17281debfc3dSmrg
17291debfc3dSmrg template<typename _Tp1>
17301debfc3dSmrg bool
17311debfc3dSmrg owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const noexcept
17321debfc3dSmrg { return _M_refcount._M_less(__rhs._M_refcount); }
17331debfc3dSmrg
17341debfc3dSmrg template<typename _Tp1>
17351debfc3dSmrg bool
17361debfc3dSmrg owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept
17371debfc3dSmrg { return _M_refcount._M_less(__rhs._M_refcount); }
17381debfc3dSmrg
17391debfc3dSmrg void
17401debfc3dSmrg reset() noexcept
17411debfc3dSmrg { __weak_ptr().swap(*this); }
17421debfc3dSmrg
17431debfc3dSmrg void
17441debfc3dSmrg swap(__weak_ptr& __s) noexcept
17451debfc3dSmrg {
17461debfc3dSmrg std::swap(_M_ptr, __s._M_ptr);
17471debfc3dSmrg _M_refcount._M_swap(__s._M_refcount);
17481debfc3dSmrg }
17491debfc3dSmrg
17501debfc3dSmrg private:
17511debfc3dSmrg // Used by __enable_shared_from_this.
17521debfc3dSmrg void
17531debfc3dSmrg _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) noexcept
17541debfc3dSmrg {
17551debfc3dSmrg if (use_count() == 0)
17561debfc3dSmrg {
17571debfc3dSmrg _M_ptr = __ptr;
17581debfc3dSmrg _M_refcount = __refcount;
17591debfc3dSmrg }
17601debfc3dSmrg }
17611debfc3dSmrg
17621debfc3dSmrg template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
17631debfc3dSmrg template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
17641debfc3dSmrg friend class __enable_shared_from_this<_Tp, _Lp>;
17651debfc3dSmrg friend class enable_shared_from_this<_Tp>;
17661debfc3dSmrg
17671debfc3dSmrg element_type* _M_ptr; // Contained pointer.
17681debfc3dSmrg __weak_count<_Lp> _M_refcount; // Reference counter.
17691debfc3dSmrg };
17701debfc3dSmrg
17711debfc3dSmrg // 20.7.2.3.6 weak_ptr specialized algorithms.
17721debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
17731debfc3dSmrg inline void
17741debfc3dSmrg swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) noexcept
17751debfc3dSmrg { __a.swap(__b); }
17761debfc3dSmrg
17771debfc3dSmrg template<typename _Tp, typename _Tp1>
17781debfc3dSmrg struct _Sp_owner_less : public binary_function<_Tp, _Tp, bool>
17791debfc3dSmrg {
17801debfc3dSmrg bool
17811debfc3dSmrg operator()(const _Tp& __lhs, const _Tp& __rhs) const noexcept
17821debfc3dSmrg { return __lhs.owner_before(__rhs); }
17831debfc3dSmrg
17841debfc3dSmrg bool
17851debfc3dSmrg operator()(const _Tp& __lhs, const _Tp1& __rhs) const noexcept
17861debfc3dSmrg { return __lhs.owner_before(__rhs); }
17871debfc3dSmrg
17881debfc3dSmrg bool
17891debfc3dSmrg operator()(const _Tp1& __lhs, const _Tp& __rhs) const noexcept
17901debfc3dSmrg { return __lhs.owner_before(__rhs); }
17911debfc3dSmrg };
17921debfc3dSmrg
17931debfc3dSmrg template<>
17941debfc3dSmrg struct _Sp_owner_less<void, void>
17951debfc3dSmrg {
17961debfc3dSmrg template<typename _Tp, typename _Up>
17971debfc3dSmrg auto
17981debfc3dSmrg operator()(const _Tp& __lhs, const _Up& __rhs) const noexcept
17991debfc3dSmrg -> decltype(__lhs.owner_before(__rhs))
18001debfc3dSmrg { return __lhs.owner_before(__rhs); }
18011debfc3dSmrg
18021debfc3dSmrg using is_transparent = void;
18031debfc3dSmrg };
18041debfc3dSmrg
18051debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
18061debfc3dSmrg struct owner_less<__shared_ptr<_Tp, _Lp>>
18071debfc3dSmrg : public _Sp_owner_less<__shared_ptr<_Tp, _Lp>, __weak_ptr<_Tp, _Lp>>
18081debfc3dSmrg { };
18091debfc3dSmrg
18101debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
18111debfc3dSmrg struct owner_less<__weak_ptr<_Tp, _Lp>>
18121debfc3dSmrg : public _Sp_owner_less<__weak_ptr<_Tp, _Lp>, __shared_ptr<_Tp, _Lp>>
18131debfc3dSmrg { };
18141debfc3dSmrg
18151debfc3dSmrg
18161debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
18171debfc3dSmrg class __enable_shared_from_this
18181debfc3dSmrg {
18191debfc3dSmrg protected:
18201debfc3dSmrg constexpr __enable_shared_from_this() noexcept { }
18211debfc3dSmrg
18221debfc3dSmrg __enable_shared_from_this(const __enable_shared_from_this&) noexcept { }
18231debfc3dSmrg
18241debfc3dSmrg __enable_shared_from_this&
18251debfc3dSmrg operator=(const __enable_shared_from_this&) noexcept
18261debfc3dSmrg { return *this; }
18271debfc3dSmrg
18281debfc3dSmrg ~__enable_shared_from_this() { }
18291debfc3dSmrg
18301debfc3dSmrg public:
18311debfc3dSmrg __shared_ptr<_Tp, _Lp>
18321debfc3dSmrg shared_from_this()
18331debfc3dSmrg { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); }
18341debfc3dSmrg
18351debfc3dSmrg __shared_ptr<const _Tp, _Lp>
18361debfc3dSmrg shared_from_this() const
18371debfc3dSmrg { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); }
18381debfc3dSmrg
18391debfc3dSmrg #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
18401debfc3dSmrg __weak_ptr<_Tp, _Lp>
18411debfc3dSmrg weak_from_this() noexcept
18421debfc3dSmrg { return this->_M_weak_this; }
18431debfc3dSmrg
18441debfc3dSmrg __weak_ptr<const _Tp, _Lp>
18451debfc3dSmrg weak_from_this() const noexcept
18461debfc3dSmrg { return this->_M_weak_this; }
18471debfc3dSmrg #endif
18481debfc3dSmrg
18491debfc3dSmrg private:
18501debfc3dSmrg template<typename _Tp1>
18511debfc3dSmrg void
18521debfc3dSmrg _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const noexcept
18531debfc3dSmrg { _M_weak_this._M_assign(__p, __n); }
18541debfc3dSmrg
18551debfc3dSmrg friend const __enable_shared_from_this*
18561debfc3dSmrg __enable_shared_from_this_base(const __shared_count<_Lp>&,
18571debfc3dSmrg const __enable_shared_from_this* __p)
18581debfc3dSmrg { return __p; }
18591debfc3dSmrg
18601debfc3dSmrg template<typename, _Lock_policy>
18611debfc3dSmrg friend class __shared_ptr;
18621debfc3dSmrg
18631debfc3dSmrg mutable __weak_ptr<_Tp, _Lp> _M_weak_this;
18641debfc3dSmrg };
18651debfc3dSmrg
1866c0a68be4Smrg template<typename _Tp, _Lock_policy _Lp = __default_lock_policy,
1867c0a68be4Smrg typename _Alloc, typename... _Args>
18681debfc3dSmrg inline __shared_ptr<_Tp, _Lp>
18691debfc3dSmrg __allocate_shared(const _Alloc& __a, _Args&&... __args)
18701debfc3dSmrg {
18718feb0f0bSmrg static_assert(!is_array<_Tp>::value, "make_shared<T[]> not supported");
18728feb0f0bSmrg
1873a2dc1f3fSmrg return __shared_ptr<_Tp, _Lp>(_Sp_alloc_shared_tag<_Alloc>{__a},
18741debfc3dSmrg std::forward<_Args>(__args)...);
18751debfc3dSmrg }
18761debfc3dSmrg
1877c0a68be4Smrg template<typename _Tp, _Lock_policy _Lp = __default_lock_policy,
1878c0a68be4Smrg typename... _Args>
18791debfc3dSmrg inline __shared_ptr<_Tp, _Lp>
18801debfc3dSmrg __make_shared(_Args&&... __args)
18811debfc3dSmrg {
18821debfc3dSmrg typedef typename std::remove_const<_Tp>::type _Tp_nc;
18831debfc3dSmrg return std::__allocate_shared<_Tp, _Lp>(std::allocator<_Tp_nc>(),
18841debfc3dSmrg std::forward<_Args>(__args)...);
18851debfc3dSmrg }
18861debfc3dSmrg
18871debfc3dSmrg /// std::hash specialization for __shared_ptr.
18881debfc3dSmrg template<typename _Tp, _Lock_policy _Lp>
18891debfc3dSmrg struct hash<__shared_ptr<_Tp, _Lp>>
18901debfc3dSmrg : public __hash_base<size_t, __shared_ptr<_Tp, _Lp>>
18911debfc3dSmrg {
18921debfc3dSmrg size_t
18931debfc3dSmrg operator()(const __shared_ptr<_Tp, _Lp>& __s) const noexcept
18941debfc3dSmrg {
18951debfc3dSmrg return hash<typename __shared_ptr<_Tp, _Lp>::element_type*>()(
18961debfc3dSmrg __s.get());
18971debfc3dSmrg }
18981debfc3dSmrg };
18991debfc3dSmrg
19001debfc3dSmrg _GLIBCXX_END_NAMESPACE_VERSION
19011debfc3dSmrg } // namespace
19021debfc3dSmrg
19031debfc3dSmrg #endif // _SHARED_PTR_BASE_H
1904