+ struct auto_ptr_ref
+ {
+ _Tp1* _M_ptr;
+
+ explicit
+ auto_ptr_ref(_Tp1* __p): _M_ptr(__p) { }
+ } _GLIBCXX_DEPRECATED;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+ /**
+ * @brief A simple smart pointer providing strict ownership semantics.
+ *
+ * The Standard says:
+ *
+ * An @c auto_ptr owns the object it holds a pointer to. Copying
+ * an @c auto_ptr copies the pointer and transfers ownership to the
+ * destination. If more than one @c auto_ptr owns the same object
+ * at the same time the behavior of the program is undefined.
+ *
+ * The uses of @c auto_ptr include providing temporary
+ * exception-safety for dynamically allocated memory, passing
+ * ownership of dynamically allocated memory to a function, and
+ * returning dynamically allocated memory from a function. @c
+ * auto_ptr does not meet the CopyConstructible and Assignable
+ * requirements for Standard Library container elements and thus
+ * instantiating a Standard Library container with an @c auto_ptr
+ * results in undefined behavior.
+ *
+ * Quoted from [20.4.5]/3.
+ *
+ * Good examples of what can and cannot be done with auto_ptr can
+ * be found in the libstdc++ testsuite.
+ *
+ * _GLIBCXX_RESOLVE_LIB_DEFECTS
+ * 127. auto_ptr<> conversion issues
+ * These resolutions have all been incorporated.
+ */
+ template
+ class auto_ptr
+ {
+ private:
+ _Tp* _M_ptr;
+
+ public:
+ /// The pointed-to type.
+ typedef _Tp element_type;
+
+ /**
+ * @brief An %auto_ptr is usually constructed from a raw pointer.
+ * @param __p A pointer (defaults to NULL).
+ *
+ * This object now @e owns the object pointed to by @a __p.
+ */
+ explicit
+ auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }
+
+ /**
+ * @brief An %auto_ptr can be constructed from another %auto_ptr.
+ * @param __a Another %auto_ptr of the same type.
+ *
+ * This object now @e owns the object previously owned by @a __a,
+ * which has given up ownership.
+ */
+ auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { }
+
+ /**
+ * @brief An %auto_ptr can be constructed from another %auto_ptr.
+ * @param __a Another %auto_ptr of a different but related type.
+ *
+ * A pointer-to-Tp1 must be convertible to a
+ * pointer-to-Tp/element_type.
+ *
+ * This object now @e owns the object previously owned by @a __a,
+ * which has given up ownership.
+ */
+ template
+ auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { }
+
+ /**
+ * @brief %auto_ptr assignment operator.
+ * @param __a Another %auto_ptr of the same type.
+ *
+ * This object now @e owns the object previously owned by @a __a,
+ * which has given up ownership. The object that this one @e
+ * used to own and track has been deleted.
+ */
+ auto_ptr&
+ operator=(auto_ptr& __a) throw()
+ {
+ reset(__a.release());
+ return *this;
+ }
+
+ /**
+ * @brief %auto_ptr assignment operator.
+ * @param __a Another %auto_ptr of a different but related type.
+ *
+ * A pointer-to-Tp1 must be convertible to a pointer-to-Tp/element_type.
+ *
+ * This object now @e owns the object previously owned by @a __a,
+ * which has given up ownership. The object that this one @e
+ * used to own and track has been deleted.
+ */
+ template
+ auto_ptr&
+ operator=(auto_ptr<_Tp1>& __a) throw()
+ {
+ reset(__a.release());
+ return *this;
+ }
+
+ /**
+ * When the %auto_ptr goes out of scope, the object it owns is
+ * deleted. If it no longer owns anything (i.e., @c get() is
+ * @c NULL), then this has no effect.
+ *
+ * The C++ standard says there is supposed to be an empty throw
+ * specification here, but omitting it is standard conforming. Its
+ * presence can be detected only if _Tp::~_Tp() throws, but this is
+ * prohibited. [17.4.3.6]/2
+ */
+ ~auto_ptr() { delete _M_ptr; }
+
+ /**
+ * @brief Smart pointer dereferencing.
+ *
+ * If this %auto_ptr no longer owns anything, then this
+ * operation will crash. (For a smart pointer, no longer owns
+ * anything is the same as being a null pointer, and you know
+ * what happens when you dereference one of those...)
+ */
+ element_type&
+ operator*() const throw()
+ {
+ __glibcxx_assert(_M_ptr != 0);
+ return *_M_ptr;
+ }
+
+ /**
+ * @brief Smart pointer dereferencing.
+ *
+ * This returns the pointer itself, which the language then will
+ * automatically cause to be dereferenced.
+ */
+ element_type*
+ operator->() const throw()
+ {
+ __glibcxx_assert(_M_ptr != 0);
+ return _M_ptr;
+ }
+
+ /**
+ * @brief Bypassing the smart pointer.
+ * @return The raw pointer being managed.
+ *
+ * You can get a copy of the pointer that this object owns, for
+ * situations such as passing to a function which only accepts
+ * a raw pointer.
+ *
+ * @note This %auto_ptr still owns the memory.
+ */
+ element_type*
+ get() const throw() { return _M_ptr; }
+
+ /**
+ * @brief Bypassing the smart pointer.
+ * @return The raw pointer being managed.
+ *
+ * You can get a copy of the pointer that this object owns, for
+ * situations such as passing to a function which only accepts
+ * a raw pointer.
+ *
+ * @note This %auto_ptr no longer owns the memory. When this object
+ * goes out of scope, nothing will happen.
+ */
+ element_type*
+ release() throw()
+ {
+ element_type* __tmp = _M_ptr;
+ _M_ptr = 0;
+ return __tmp;
+ }
+
+ /**
+ * @brief Forcibly deletes the managed object.
+ * @param __p A pointer (defaults to NULL).
+ *
+ * This object now @e owns the object pointed to by @a __p. The
+ * previous object has been deleted.
+ */
+ void
+ reset(element_type* __p = 0) throw()
+ {
+ if (__p != _M_ptr)
+ {
+ delete _M_ptr;
+ _M_ptr = __p;
+ }
+ }
+
+ /**
+ * @brief Automatic conversions
+ *
+ * These operations are supposed to convert an %auto_ptr into and from
+ * an auto_ptr_ref automatically as needed. This would allow
+ * constructs such as
+ * @code
+ * auto_ptr func_returning_auto_ptr(.....);
+ * ...
+ * auto_ptr ptr = func_returning_auto_ptr(.....);
+ * @endcode
+ *
+ * But it doesn't work, and won't be fixed. For further details see
+ * http://cplusplus.github.io/LWG/lwg-closed.html#463
+ */
+ auto_ptr(auto_ptr_ref __ref) throw()
+ : _M_ptr(__ref._M_ptr) { }
+
+ auto_ptr&
+ operator=(auto_ptr_ref __ref) throw()
+ {
+ if (__ref._M_ptr != this->get())
+ {
+ delete _M_ptr;
+ _M_ptr = __ref._M_ptr;
+ }
+ return *this;
+ }
+
+ template
+ operator auto_ptr_ref<_Tp1>() throw()
+ { return auto_ptr_ref<_Tp1>(this->release()); }
+
+ template
+ operator auto_ptr<_Tp1>() throw()
+ { return auto_ptr<_Tp1>(this->release()); }
+ } _GLIBCXX_DEPRECATED;
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 541. shared_ptr template assignment and void
+ template<>
+ class auto_ptr
+ {
+ public:
+ typedef void element_type;
+ } _GLIBCXX_DEPRECATED;
+
+#if __cplusplus >= 201103L
+ template<_Lock_policy _Lp>
+ template
+ inline
+ __shared_count<_Lp>::__shared_count(std::auto_ptr<_Tp>&& __r)
+ : _M_pi(new _Sp_counted_ptr<_Tp*, _Lp>(__r.get()))
+ { __r.release(); }
+
+ template
+ template
+ inline
+ __shared_ptr<_Tp, _Lp>::__shared_ptr(std::auto_ptr<_Tp1>&& __r)
+ : _M_ptr(__r.get()), _M_refcount()
+ {
+ __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
+ static_assert( sizeof(_Tp1) > 0, "incomplete type" );
+ _Tp1* __tmp = __r.get();
+ _M_refcount = __shared_count<_Lp>(std::move(__r));
+ _M_enable_shared_from_this_with(__tmp);
+ }
+
+ template
+ template
+ inline
+ shared_ptr<_Tp>::shared_ptr(std::auto_ptr<_Tp1>&& __r)
+ : __shared_ptr<_Tp>(std::move(__r)) { }
+
+ template
+ template
+ inline
+ unique_ptr<_Tp, _Dp>::unique_ptr(auto_ptr<_Up>&& __u) noexcept
+ : _M_t(__u.release(), deleter_type()) { }
+#endif
+
+#pragma GCC diagnostic pop
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif /* _BACKWARD_AUTO_PTR_H */
diff --git a/include/bits/shared_ptr.h b/include/bits/shared_ptr.h
new file mode 100644
index 0000000..0c393e2
--- /dev/null
+++ b/include/bits/shared_ptr.h
@@ -0,0 +1,918 @@
+// shared_ptr and weak_ptr implementation -*- C++ -*-
+
+// Copyright (C) 2007-2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// .
+
+// GCC Note: Based on files from version 1.32.0 of the Boost library.
+
+// shared_count.hpp
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+
+// shared_ptr.hpp
+// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
+// Copyright (C) 2001, 2002, 2003 Peter Dimov
+
+// weak_ptr.hpp
+// Copyright (C) 2001, 2002, 2003 Peter Dimov
+
+// enable_shared_from_this.hpp
+// Copyright (C) 2002 Peter Dimov
+
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/** @file
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{memory}
+ */
+
+#ifndef _SHARED_PTR_H
+#define _SHARED_PTR_H 1
+
+#include
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /**
+ * @addtogroup pointer_abstractions
+ * @{
+ */
+
+ // 20.7.2.2.11 shared_ptr I/O
+
+ /// Write the stored pointer to an ostream.
+ /// @relates shared_ptr
+ template
+ inline std::basic_ostream<_Ch, _Tr>&
+ operator<<(std::basic_ostream<_Ch, _Tr>& __os,
+ const __shared_ptr<_Tp, _Lp>& __p)
+ {
+ __os << __p.get();
+ return __os;
+ }
+
+ template
+ inline _Del*
+ get_deleter(const __shared_ptr<_Tp, _Lp>& __p) noexcept
+ {
+#if __cpp_rtti
+ return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
+#else
+ return 0;
+#endif
+ }
+
+ /// 20.7.2.2.10 shared_ptr get_deleter
+
+ /// If `__p` has a deleter of type `_Del`, return a pointer to it.
+ /// @relates shared_ptr
+ template
+ inline _Del*
+ get_deleter(const shared_ptr<_Tp>& __p) noexcept
+ {
+#if __cpp_rtti
+ return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
+#else
+ return 0;
+#endif
+ }
+
+ /**
+ * @brief A smart pointer with reference-counted copy semantics.
+ *
+ * A `shared_ptr` object is either empty or _owns_ a pointer passed
+ * to the constructor. Copies of a `shared_ptr` share ownership of
+ * the same pointer. When the last `shared_ptr` that owns the pointer
+ * is destroyed or reset, the owned pointer is freed (either by `delete`
+ * or by invoking a custom deleter that was passed to the constructor).
+ *
+ * A `shared_ptr` also stores another pointer, which is usually
+ * (but not always) the same pointer as it owns. The stored pointer
+ * can be retrieved by calling the `get()` member function.
+ *
+ * The equality and relational operators for `shared_ptr` only compare
+ * the stored pointer returned by `get()`, not the owned pointer.
+ * To test whether two `shared_ptr` objects share ownership of the same
+ * pointer see `std::shared_ptr::owner_before` and `std::owner_less`.
+ */
+ template
+ class shared_ptr : public __shared_ptr<_Tp>
+ {
+ template
+ using _Constructible = typename enable_if<
+ is_constructible<__shared_ptr<_Tp>, _Args...>::value
+ >::type;
+
+ template
+ using _Assignable = typename enable_if<
+ is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr&
+ >::type;
+
+ public:
+
+ /// The type pointed to by the stored pointer, remove_extent_t<_Tp>
+ using element_type = typename __shared_ptr<_Tp>::element_type;
+
+#if __cplusplus >= 201703L
+# define __cpp_lib_shared_ptr_weak_type 201606
+ /// The corresponding weak_ptr type for this shared_ptr
+ using weak_type = weak_ptr<_Tp>;
+#endif
+ /**
+ * @brief Construct an empty %shared_ptr.
+ * @post use_count()==0 && get()==0
+ */
+ constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { }
+
+ shared_ptr(const shared_ptr&) noexcept = default; ///< Copy constructor
+
+ /**
+ * @brief Construct a %shared_ptr that owns the pointer @a __p.
+ * @param __p A pointer that is convertible to element_type*.
+ * @post use_count() == 1 && get() == __p
+ * @throw std::bad_alloc, in which case @c delete @a __p is called.
+ */
+ template>
+ explicit
+ shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
+
+ /**
+ * @brief Construct a %shared_ptr that owns the pointer @a __p
+ * and the deleter @a __d.
+ * @param __p A pointer.
+ * @param __d A deleter.
+ * @post use_count() == 1 && get() == __p
+ * @throw std::bad_alloc, in which case @a __d(__p) is called.
+ *
+ * Requirements: _Deleter's copy constructor and destructor must
+ * not throw
+ *
+ * __shared_ptr will release __p by calling __d(__p)
+ */
+ template>
+ shared_ptr(_Yp* __p, _Deleter __d)
+ : __shared_ptr<_Tp>(__p, std::move(__d)) { }
+
+ /**
+ * @brief Construct a %shared_ptr that owns a null pointer
+ * and the deleter @a __d.
+ * @param __p A null pointer constant.
+ * @param __d A deleter.
+ * @post use_count() == 1 && get() == __p
+ * @throw std::bad_alloc, in which case @a __d(__p) is called.
+ *
+ * Requirements: _Deleter's copy constructor and destructor must
+ * not throw
+ *
+ * The last owner will call __d(__p)
+ */
+ template
+ shared_ptr(nullptr_t __p, _Deleter __d)
+ : __shared_ptr<_Tp>(__p, std::move(__d)) { }
+
+ /**
+ * @brief Construct a %shared_ptr that owns the pointer @a __p
+ * and the deleter @a __d.
+ * @param __p A pointer.
+ * @param __d A deleter.
+ * @param __a An allocator.
+ * @post use_count() == 1 && get() == __p
+ * @throw std::bad_alloc, in which case @a __d(__p) is called.
+ *
+ * Requirements: _Deleter's copy constructor and destructor must
+ * not throw _Alloc's copy constructor and destructor must not
+ * throw.
+ *
+ * __shared_ptr will release __p by calling __d(__p)
+ */
+ template>
+ shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
+ : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
+
+ /**
+ * @brief Construct a %shared_ptr that owns a null pointer
+ * and the deleter @a __d.
+ * @param __p A null pointer constant.
+ * @param __d A deleter.
+ * @param __a An allocator.
+ * @post use_count() == 1 && get() == __p
+ * @throw std::bad_alloc, in which case @a __d(__p) is called.
+ *
+ * Requirements: _Deleter's copy constructor and destructor must
+ * not throw _Alloc's copy constructor and destructor must not
+ * throw.
+ *
+ * The last owner will call __d(__p)
+ */
+ template
+ shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
+ : __shared_ptr<_Tp>(__p, std::move(__d), std::move(__a)) { }
+
+ // Aliasing constructor
+
+ /**
+ * @brief Constructs a `shared_ptr` instance that stores `__p`
+ * and shares ownership with `__r`.
+ * @param __r A `shared_ptr`.
+ * @param __p A pointer that will remain valid while `*__r` is valid.
+ * @post `get() == __p && use_count() == __r.use_count()`
+ *
+ * This can be used to construct a `shared_ptr` to a sub-object
+ * of an object managed by an existing `shared_ptr`. The complete
+ * object will remain valid while any `shared_ptr` owns it, even
+ * if they don't store a pointer to the complete object.
+ *
+ * @code
+ * shared_ptr> pii(new pair());
+ * shared_ptr pi(pii, &pii->first);
+ * assert(pii.use_count() == 2);
+ * @endcode
+ */
+ template
+ shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
+ : __shared_ptr<_Tp>(__r, __p) { }
+
+#if __cplusplus > 201703L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2996. Missing rvalue overloads for shared_ptr operations
+ /**
+ * @brief Constructs a `shared_ptr` instance that stores `__p`
+ * and shares ownership with `__r`.
+ * @param __r A `shared_ptr`.
+ * @param __p A pointer that will remain valid while `*__r` is valid.
+ * @post `get() == __p && !__r.use_count() && !__r.get()`
+ *
+ * This can be used to construct a `shared_ptr` to a sub-object
+ * of an object managed by an existing `shared_ptr`. The complete
+ * object will remain valid while any `shared_ptr` owns it, even
+ * if they don't store a pointer to the complete object.
+ *
+ * @code
+ * shared_ptr> pii(new pair());
+ * shared_ptr pi1(pii, &pii->first);
+ * assert(pii.use_count() == 2);
+ * shared_ptr pi2(std::move(pii), &pii->second);
+ * assert(pii.use_count() == 0);
+ * @endcode
+ */
+ template
+ shared_ptr(shared_ptr<_Yp>&& __r, element_type* __p) noexcept
+ : __shared_ptr<_Tp>(std::move(__r), __p) { }
+#endif
+ /**
+ * @brief If @a __r is empty, constructs an empty %shared_ptr;
+ * otherwise construct a %shared_ptr that shares ownership
+ * with @a __r.
+ * @param __r A %shared_ptr.
+ * @post get() == __r.get() && use_count() == __r.use_count()
+ */
+ template&>>
+ shared_ptr(const shared_ptr<_Yp>& __r) noexcept
+ : __shared_ptr<_Tp>(__r) { }
+
+ /**
+ * @brief Move-constructs a %shared_ptr instance from @a __r.
+ * @param __r A %shared_ptr rvalue.
+ * @post *this contains the old value of @a __r, @a __r is empty.
+ */
+ shared_ptr(shared_ptr&& __r) noexcept
+ : __shared_ptr<_Tp>(std::move(__r)) { }
+
+ /**
+ * @brief Move-constructs a %shared_ptr instance from @a __r.
+ * @param __r A %shared_ptr rvalue.
+ * @post *this contains the old value of @a __r, @a __r is empty.
+ */
+ template>>
+ shared_ptr(shared_ptr<_Yp>&& __r) noexcept
+ : __shared_ptr<_Tp>(std::move(__r)) { }
+
+ /**
+ * @brief Constructs a %shared_ptr that shares ownership with @a __r
+ * and stores a copy of the pointer stored in @a __r.
+ * @param __r A weak_ptr.
+ * @post use_count() == __r.use_count()
+ * @throw bad_weak_ptr when __r.expired(),
+ * in which case the constructor has no effect.
+ */
+ template&>>
+ explicit shared_ptr(const weak_ptr<_Yp>& __r)
+ : __shared_ptr<_Tp>(__r) { }
+
+#if _GLIBCXX_USE_DEPRECATED
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ template>>
+ shared_ptr(auto_ptr<_Yp>&& __r);
+#pragma GCC diagnostic pop
+#endif
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2399. shared_ptr's constructor from unique_ptr should be constrained
+ template>>
+ shared_ptr(unique_ptr<_Yp, _Del>&& __r)
+ : __shared_ptr<_Tp>(std::move(__r)) { }
+
+#if __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATED
+ // This non-standard constructor exists to support conversions that
+ // were possible in C++11 and C++14 but are ill-formed in C++17.
+ // If an exception is thrown this constructor has no effect.
+ template, __sp_array_delete>* = 0>
+ shared_ptr(unique_ptr<_Yp, _Del>&& __r)
+ : __shared_ptr<_Tp>(std::move(__r), __sp_array_delete()) { }
+#endif
+
+ /**
+ * @brief Construct an empty %shared_ptr.
+ * @post use_count() == 0 && get() == nullptr
+ */
+ constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
+
+ shared_ptr& operator=(const shared_ptr&) noexcept = default;
+
+ template
+ _Assignable&>
+ operator=(const shared_ptr<_Yp>& __r) noexcept
+ {
+ this->__shared_ptr<_Tp>::operator=(__r);
+ return *this;
+ }
+
+#if _GLIBCXX_USE_DEPRECATED
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ template
+ _Assignable>
+ operator=(auto_ptr<_Yp>&& __r)
+ {
+ this->__shared_ptr<_Tp>::operator=(std::move(__r));
+ return *this;
+ }
+#pragma GCC diagnostic pop
+#endif
+
+ shared_ptr&
+ operator=(shared_ptr&& __r) noexcept
+ {
+ this->__shared_ptr<_Tp>::operator=(std::move(__r));
+ return *this;
+ }
+
+ template
+ _Assignable>
+ operator=(shared_ptr<_Yp>&& __r) noexcept
+ {
+ this->__shared_ptr<_Tp>::operator=(std::move(__r));
+ return *this;
+ }
+
+ template
+ _Assignable>
+ operator=(unique_ptr<_Yp, _Del>&& __r)
+ {
+ this->__shared_ptr<_Tp>::operator=(std::move(__r));
+ return *this;
+ }
+
+ private:
+ // This constructor is non-standard, it is used by allocate_shared.
+ template
+ shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
+ : __shared_ptr<_Tp>(__tag, std::forward<_Args>(__args)...)
+ { }
+
+ template
+ friend shared_ptr<_Yp>
+ allocate_shared(const _Alloc& __a, _Args&&... __args);
+
+ // This constructor is non-standard, it is used by weak_ptr::lock().
+ shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
+ : __shared_ptr<_Tp>(__r, std::nothrow) { }
+
+ friend class weak_ptr<_Tp>;
+ };
+
+#if __cpp_deduction_guides >= 201606
+ template
+ shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>;
+ template
+ shared_ptr(unique_ptr<_Tp, _Del>) -> shared_ptr<_Tp>;
+#endif
+
+ // 20.7.2.2.7 shared_ptr comparisons
+
+ /// @relates shared_ptr @{
+
+ /// Equality operator for shared_ptr objects, compares the stored pointers
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator==(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
+ { return __a.get() == __b.get(); }
+
+ /// shared_ptr comparison with nullptr
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+ { return !__a; }
+
+#ifdef __cpp_lib_three_way_comparison
+ template
+ inline strong_ordering
+ operator<=>(const shared_ptr<_Tp>& __a,
+ const shared_ptr<_Up>& __b) noexcept
+ { return compare_three_way()(__a.get(), __b.get()); }
+
+ template
+ inline strong_ordering
+ operator<=>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+ {
+ using pointer = typename shared_ptr<_Tp>::element_type*;
+ return compare_three_way()(__a.get(), static_cast(nullptr));
+ }
+#else
+ /// shared_ptr comparison with nullptr
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+ { return !__a; }
+
+ /// Inequality operator for shared_ptr objects, compares the stored pointers
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator!=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
+ { return __a.get() != __b.get(); }
+
+ /// shared_ptr comparison with nullptr
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+ { return (bool)__a; }
+
+ /// shared_ptr comparison with nullptr
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+ { return (bool)__a; }
+
+ /// Relational operator for shared_ptr objects, compares the stored pointers
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator<(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
+ {
+ using _Tp_elt = typename shared_ptr<_Tp>::element_type;
+ using _Up_elt = typename shared_ptr<_Up>::element_type;
+ using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
+ return less<_Vp>()(__a.get(), __b.get());
+ }
+
+ /// shared_ptr comparison with nullptr
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+ {
+ using _Tp_elt = typename shared_ptr<_Tp>::element_type;
+ return less<_Tp_elt*>()(__a.get(), nullptr);
+ }
+
+ /// shared_ptr comparison with nullptr
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+ {
+ using _Tp_elt = typename shared_ptr<_Tp>::element_type;
+ return less<_Tp_elt*>()(nullptr, __a.get());
+ }
+
+ /// Relational operator for shared_ptr objects, compares the stored pointers
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator<=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
+ { return !(__b < __a); }
+
+ /// shared_ptr comparison with nullptr
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+ { return !(nullptr < __a); }
+
+ /// shared_ptr comparison with nullptr
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+ { return !(__a < nullptr); }
+
+ /// Relational operator for shared_ptr objects, compares the stored pointers
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator>(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
+ { return (__b < __a); }
+
+ /// shared_ptr comparison with nullptr
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+ { return nullptr < __a; }
+
+ /// shared_ptr comparison with nullptr
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+ { return __a < nullptr; }
+
+ /// Relational operator for shared_ptr objects, compares the stored pointers
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator>=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
+ { return !(__a < __b); }
+
+ /// shared_ptr comparison with nullptr
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
+ { return !(__a < nullptr); }
+
+ /// shared_ptr comparison with nullptr
+ template
+ _GLIBCXX_NODISCARD inline bool
+ operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
+ { return !(nullptr < __a); }
+#endif
+
+ // 20.7.2.2.8 shared_ptr specialized algorithms.
+
+ /// Swap overload for shared_ptr
+ template
+ inline void
+ swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
+ { __a.swap(__b); }
+
+ // 20.7.2.2.9 shared_ptr casts.
+
+ /// Convert type of `shared_ptr`, via `static_cast`
+ template
+ inline shared_ptr<_Tp>
+ static_pointer_cast(const shared_ptr<_Up>& __r) noexcept
+ {
+ using _Sp = shared_ptr<_Tp>;
+ return _Sp(__r, static_cast(__r.get()));
+ }
+
+ /// Convert type of `shared_ptr`, via `const_cast`
+ template
+ inline shared_ptr<_Tp>
+ const_pointer_cast(const shared_ptr<_Up>& __r) noexcept
+ {
+ using _Sp = shared_ptr<_Tp>;
+ return _Sp(__r, const_cast(__r.get()));
+ }
+
+ /// Convert type of `shared_ptr`, via `dynamic_cast`
+ template
+ inline shared_ptr<_Tp>
+ dynamic_pointer_cast(const shared_ptr<_Up>& __r) noexcept
+ {
+ using _Sp = shared_ptr<_Tp>;
+ if (auto* __p = dynamic_cast(__r.get()))
+ return _Sp(__r, __p);
+ return _Sp();
+ }
+
+#if __cplusplus >= 201703L
+ /// Convert type of `shared_ptr`, via `reinterpret_cast`
+ template
+ inline shared_ptr<_Tp>
+ reinterpret_pointer_cast(const shared_ptr<_Up>& __r) noexcept
+ {
+ using _Sp = shared_ptr<_Tp>;
+ return _Sp(__r, reinterpret_cast(__r.get()));
+ }
+
+#if __cplusplus > 201703L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2996. Missing rvalue overloads for shared_ptr operations
+
+ /// Convert type of `shared_ptr` rvalue, via `static_cast`
+ template
+ inline shared_ptr<_Tp>
+ static_pointer_cast(shared_ptr<_Up>&& __r) noexcept
+ {
+ using _Sp = shared_ptr<_Tp>;
+ return _Sp(std::move(__r),
+ static_cast(__r.get()));
+ }
+
+ /// Convert type of `shared_ptr` rvalue, via `const_cast`
+ template
+ inline shared_ptr<_Tp>
+ const_pointer_cast(shared_ptr<_Up>&& __r) noexcept
+ {
+ using _Sp = shared_ptr<_Tp>;
+ return _Sp(std::move(__r),
+ const_cast(__r.get()));
+ }
+
+ /// Convert type of `shared_ptr` rvalue, via `dynamic_cast`
+ template
+ inline shared_ptr<_Tp>
+ dynamic_pointer_cast(shared_ptr<_Up>&& __r) noexcept
+ {
+ using _Sp = shared_ptr<_Tp>;
+ if (auto* __p = dynamic_cast(__r.get()))
+ return _Sp(std::move(__r), __p);
+ return _Sp();
+ }
+
+ /// Convert type of `shared_ptr` rvalue, via `reinterpret_cast`
+ template
+ inline shared_ptr<_Tp>
+ reinterpret_pointer_cast(shared_ptr<_Up>&& __r) noexcept
+ {
+ using _Sp = shared_ptr<_Tp>;
+ return _Sp(std::move(__r),
+ reinterpret_cast(__r.get()));
+ }
+#endif // C++20
+#endif // C++17
+
+ // @}
+
+ /**
+ * @brief A non-owning observer for a pointer owned by a shared_ptr
+ *
+ * A weak_ptr provides a safe alternative to a raw pointer when you want
+ * a non-owning reference to an object that is managed by a shared_ptr.
+ *
+ * Unlike a raw pointer, a weak_ptr can be converted to a new shared_ptr
+ * that shares ownership with every other shared_ptr that already owns
+ * the pointer. In other words you can upgrade from a non-owning "weak"
+ * reference to an owning shared_ptr, without having access to any of
+ * the existing shared_ptr objects.
+ *
+ * Also unlike a raw pointer, a weak_ptr does not become "dangling" after
+ * the object it points to has been destroyed. Instead, a weak_ptr
+ * becomes _expired_ and can no longer be converted to a shared_ptr that
+ * owns the freed pointer, so you cannot accidentally access the pointed-to
+ * object after it has been destroyed.
+ */
+ template
+ class weak_ptr : public __weak_ptr<_Tp>
+ {
+ template
+ using _Constructible = typename enable_if<
+ is_constructible<__weak_ptr<_Tp>, _Arg>::value
+ >::type;
+
+ template
+ using _Assignable = typename enable_if<
+ is_assignable<__weak_ptr<_Tp>&, _Arg>::value, weak_ptr&
+ >::type;
+
+ public:
+ constexpr weak_ptr() noexcept = default;
+
+ template&>>
+ weak_ptr(const shared_ptr<_Yp>& __r) noexcept
+ : __weak_ptr<_Tp>(__r) { }
+
+ weak_ptr(const weak_ptr&) noexcept = default;
+
+ template&>>
+ weak_ptr(const weak_ptr<_Yp>& __r) noexcept
+ : __weak_ptr<_Tp>(__r) { }
+
+ weak_ptr(weak_ptr&&) noexcept = default;
+
+ template>>
+ weak_ptr(weak_ptr<_Yp>&& __r) noexcept
+ : __weak_ptr<_Tp>(std::move(__r)) { }
+
+ weak_ptr&
+ operator=(const weak_ptr& __r) noexcept = default;
+
+ template
+ _Assignable&>
+ operator=(const weak_ptr<_Yp>& __r) noexcept
+ {
+ this->__weak_ptr<_Tp>::operator=(__r);
+ return *this;
+ }
+
+ template
+ _Assignable&>
+ operator=(const shared_ptr<_Yp>& __r) noexcept
+ {
+ this->__weak_ptr<_Tp>::operator=(__r);
+ return *this;
+ }
+
+ weak_ptr&
+ operator=(weak_ptr&& __r) noexcept = default;
+
+ template
+ _Assignable>
+ operator=(weak_ptr<_Yp>&& __r) noexcept
+ {
+ this->__weak_ptr<_Tp>::operator=(std::move(__r));
+ return *this;
+ }
+
+ shared_ptr<_Tp>
+ lock() const noexcept
+ { return shared_ptr<_Tp>(*this, std::nothrow); }
+ };
+
+#if __cpp_deduction_guides >= 201606
+ template
+ weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>;
+#endif
+
+ // 20.7.2.3.6 weak_ptr specialized algorithms.
+ /// Swap overload for weak_ptr
+ /// @relates weak_ptr
+ template
+ inline void
+ swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
+ { __a.swap(__b); }
+
+
+ /// Primary template owner_less
+ template
+ struct owner_less;
+
+ /// Void specialization of owner_less compares either shared_ptr or weak_ptr
+ template<>
+ struct owner_less : _Sp_owner_less
+ { };
+
+ /// Partial specialization of owner_less for shared_ptr.
+ template
+ struct owner_less>
+ : public _Sp_owner_less, weak_ptr<_Tp>>
+ { };
+
+ /// Partial specialization of owner_less for weak_ptr.
+ template
+ struct owner_less>
+ : public _Sp_owner_less, shared_ptr<_Tp>>
+ { };
+
+ /**
+ * @brief Base class allowing use of member function shared_from_this.
+ */
+ template
+ class enable_shared_from_this
+ {
+ protected:
+ constexpr enable_shared_from_this() noexcept { }
+
+ enable_shared_from_this(const enable_shared_from_this&) noexcept { }
+
+ enable_shared_from_this&
+ operator=(const enable_shared_from_this&) noexcept
+ { return *this; }
+
+ ~enable_shared_from_this() { }
+
+ public:
+ shared_ptr<_Tp>
+ shared_from_this()
+ { return shared_ptr<_Tp>(this->_M_weak_this); }
+
+ shared_ptr
+ shared_from_this() const
+ { return shared_ptr(this->_M_weak_this); }
+
+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+#define __cpp_lib_enable_shared_from_this 201603
+ weak_ptr<_Tp>
+ weak_from_this() noexcept
+ { return this->_M_weak_this; }
+
+ weak_ptr
+ weak_from_this() const noexcept
+ { return this->_M_weak_this; }
+#endif
+
+ private:
+ template
+ void
+ _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
+ { _M_weak_this._M_assign(__p, __n); }
+
+ // Found by ADL when this is an associated class.
+ friend const enable_shared_from_this*
+ __enable_shared_from_this_base(const __shared_count<>&,
+ const enable_shared_from_this* __p)
+ { return __p; }
+
+ template
+ friend class __shared_ptr;
+
+ mutable weak_ptr<_Tp> _M_weak_this;
+ };
+
+ /// @relates shared_ptr @{
+
+ /**
+ * @brief Create an object that is owned by a shared_ptr.
+ * @param __a An allocator.
+ * @param __args Arguments for the @a _Tp object's constructor.
+ * @return A shared_ptr that owns the newly created object.
+ * @throw An exception thrown from @a _Alloc::allocate or from the
+ * constructor of @a _Tp.
+ *
+ * A copy of @a __a will be used to allocate memory for the shared_ptr
+ * and the new object.
+ */
+ template
+ inline shared_ptr<_Tp>
+ allocate_shared(const _Alloc& __a, _Args&&... __args)
+ {
+ return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
+ std::forward<_Args>(__args)...);
+ }
+
+ /**
+ * @brief Create an object that is owned by a shared_ptr.
+ * @param __args Arguments for the @a _Tp object's constructor.
+ * @return A shared_ptr that owns the newly created object.
+ * @throw std::bad_alloc, or an exception thrown from the
+ * constructor of @a _Tp.
+ */
+ template
+ inline shared_ptr<_Tp>
+ make_shared(_Args&&... __args)
+ {
+ typedef typename std::remove_cv<_Tp>::type _Tp_nc;
+ return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
+ std::forward<_Args>(__args)...);
+ }
+
+ /// std::hash specialization for shared_ptr.
+ template
+ struct hash>
+ : public __hash_base>
+ {
+ size_t
+ operator()(const shared_ptr<_Tp>& __s) const noexcept
+ {
+ return std::hash::element_type*>()(__s.get());
+ }
+ };
+
+ // @} relates shared_ptr
+ // @} group pointer_abstractions
+
+#if __cplusplus >= 201703L
+ namespace __detail::__variant
+ {
+ template struct _Never_valueless_alt; // see
+
+ // Provide the strong exception-safety guarantee when emplacing a
+ // shared_ptr into a variant.
+ template
+ struct _Never_valueless_alt>
+ : std::true_type
+ { };
+
+ // Provide the strong exception-safety guarantee when emplacing a
+ // weak_ptr into a variant.
+ template
+ struct _Never_valueless_alt>
+ : std::true_type
+ { };
+ } // namespace __detail::__variant
+#endif // C++17
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif // _SHARED_PTR_H
diff --git a/include/bits/shared_ptr_atomic.h b/include/bits/shared_ptr_atomic.h
new file mode 100644
index 0000000..13eb7f4
--- /dev/null
+++ b/include/bits/shared_ptr_atomic.h
@@ -0,0 +1,336 @@
+// shared_ptr atomic access -*- C++ -*-
+
+// Copyright (C) 2014-2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// .
+
+/** @file bits/shared_ptr_atomic.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{memory}
+ */
+
+#ifndef _SHARED_PTR_ATOMIC_H
+#define _SHARED_PTR_ATOMIC_H 1
+
+#include
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /**
+ * @addtogroup pointer_abstractions
+ * @{
+ */
+ /// @relates shared_ptr @{
+
+ /// @cond undocumented
+
+ struct _Sp_locker
+ {
+ _Sp_locker(const _Sp_locker&) = delete;
+ _Sp_locker& operator=(const _Sp_locker&) = delete;
+
+#ifdef __GTHREADS
+ explicit
+ _Sp_locker(const void*) noexcept;
+ _Sp_locker(const void*, const void*) noexcept;
+ ~_Sp_locker();
+
+ private:
+ unsigned char _M_key1;
+ unsigned char _M_key2;
+#else
+ explicit _Sp_locker(const void*, const void* = nullptr) { }
+#endif
+ };
+
+ /// @endcond
+
+ /**
+ * @brief Report whether shared_ptr atomic operations are lock-free.
+ * @param __p A non-null pointer to a shared_ptr object.
+ * @return True if atomic access to @c *__p is lock-free, false otherwise.
+ * @{
+ */
+ template
+ inline bool
+ atomic_is_lock_free(const __shared_ptr<_Tp, _Lp>* __p)
+ {
+#ifdef __GTHREADS
+ return __gthread_active_p() == 0;
+#else
+ return true;
+#endif
+ }
+
+ template
+ inline bool
+ atomic_is_lock_free(const shared_ptr<_Tp>* __p)
+ { return std::atomic_is_lock_free<_Tp, __default_lock_policy>(__p); }
+
+ // @}
+
+ /**
+ * @brief Atomic load for shared_ptr objects.
+ * @param __p A non-null pointer to a shared_ptr object.
+ * @return @c *__p
+ *
+ * The memory order shall not be @c memory_order_release or
+ * @c memory_order_acq_rel.
+ * @{
+ */
+ template
+ inline shared_ptr<_Tp>
+ atomic_load_explicit(const shared_ptr<_Tp>* __p, memory_order)
+ {
+ _Sp_locker __lock{__p};
+ return *__p;
+ }
+
+ template
+ inline shared_ptr<_Tp>
+ atomic_load(const shared_ptr<_Tp>* __p)
+ { return std::atomic_load_explicit(__p, memory_order_seq_cst); }
+
+ template
+ inline __shared_ptr<_Tp, _Lp>
+ atomic_load_explicit(const __shared_ptr<_Tp, _Lp>* __p, memory_order)
+ {
+ _Sp_locker __lock{__p};
+ return *__p;
+ }
+
+ template
+ inline __shared_ptr<_Tp, _Lp>
+ atomic_load(const __shared_ptr<_Tp, _Lp>* __p)
+ { return std::atomic_load_explicit(__p, memory_order_seq_cst); }
+ // @}
+
+ /**
+ * @brief Atomic store for shared_ptr objects.
+ * @param __p A non-null pointer to a shared_ptr object.
+ * @param __r The value to store.
+ *
+ * The memory order shall not be @c memory_order_acquire or
+ * @c memory_order_acq_rel.
+ * @{
+ */
+ template
+ inline void
+ atomic_store_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r,
+ memory_order)
+ {
+ _Sp_locker __lock{__p};
+ __p->swap(__r); // use swap so that **__p not destroyed while lock held
+ }
+
+ template
+ inline void
+ atomic_store(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
+ { std::atomic_store_explicit(__p, std::move(__r), memory_order_seq_cst); }
+
+ template
+ inline void
+ atomic_store_explicit(__shared_ptr<_Tp, _Lp>* __p,
+ __shared_ptr<_Tp, _Lp> __r,
+ memory_order)
+ {
+ _Sp_locker __lock{__p};
+ __p->swap(__r); // use swap so that **__p not destroyed while lock held
+ }
+
+ template
+ inline void
+ atomic_store(__shared_ptr<_Tp, _Lp>* __p, __shared_ptr<_Tp, _Lp> __r)
+ { std::atomic_store_explicit(__p, std::move(__r), memory_order_seq_cst); }
+ // @}
+
+ /**
+ * @brief Atomic exchange for shared_ptr objects.
+ * @param __p A non-null pointer to a shared_ptr object.
+ * @param __r New value to store in @c *__p.
+ * @return The original value of @c *__p
+ * @{
+ */
+ template
+ inline shared_ptr<_Tp>
+ atomic_exchange_explicit(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r,
+ memory_order)
+ {
+ _Sp_locker __lock{__p};
+ __p->swap(__r);
+ return __r;
+ }
+
+ template
+ inline shared_ptr<_Tp>
+ atomic_exchange(shared_ptr<_Tp>* __p, shared_ptr<_Tp> __r)
+ {
+ return std::atomic_exchange_explicit(__p, std::move(__r),
+ memory_order_seq_cst);
+ }
+
+ template
+ inline __shared_ptr<_Tp, _Lp>
+ atomic_exchange_explicit(__shared_ptr<_Tp, _Lp>* __p,
+ __shared_ptr<_Tp, _Lp> __r,
+ memory_order)
+ {
+ _Sp_locker __lock{__p};
+ __p->swap(__r);
+ return __r;
+ }
+
+ template
+ inline __shared_ptr<_Tp, _Lp>
+ atomic_exchange(__shared_ptr<_Tp, _Lp>* __p, __shared_ptr<_Tp, _Lp> __r)
+ {
+ return std::atomic_exchange_explicit(__p, std::move(__r),
+ memory_order_seq_cst);
+ }
+ // @}
+
+ /**
+ * @brief Atomic compare-and-swap for shared_ptr objects.
+ * @param __p A non-null pointer to a shared_ptr object.
+ * @param __v A non-null pointer to a shared_ptr object.
+ * @param __w A non-null pointer to a shared_ptr object.
+ * @return True if @c *__p was equivalent to @c *__v, false otherwise.
+ *
+ * The memory order for failure shall not be @c memory_order_release or
+ * @c memory_order_acq_rel, or stronger than the memory order for success.
+ * @{
+ */
+ template
+ bool
+ atomic_compare_exchange_strong_explicit(shared_ptr<_Tp>* __p,
+ shared_ptr<_Tp>* __v,
+ shared_ptr<_Tp> __w,
+ memory_order,
+ memory_order)
+ {
+ shared_ptr<_Tp> __x; // goes out of scope after __lock
+ _Sp_locker __lock{__p, __v};
+ owner_less> __less;
+ if (*__p == *__v && !__less(*__p, *__v) && !__less(*__v, *__p))
+ {
+ __x = std::move(*__p);
+ *__p = std::move(__w);
+ return true;
+ }
+ __x = std::move(*__v);
+ *__v = *__p;
+ return false;
+ }
+
+ template
+ inline bool
+ atomic_compare_exchange_strong(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v,
+ shared_ptr<_Tp> __w)
+ {
+ return std::atomic_compare_exchange_strong_explicit(__p, __v,
+ std::move(__w), memory_order_seq_cst, memory_order_seq_cst);
+ }
+
+ template
+ inline bool
+ atomic_compare_exchange_weak_explicit(shared_ptr<_Tp>* __p,
+ shared_ptr<_Tp>* __v,
+ shared_ptr<_Tp> __w,
+ memory_order __success,
+ memory_order __failure)
+ {
+ return std::atomic_compare_exchange_strong_explicit(__p, __v,
+ std::move(__w), __success, __failure);
+ }
+
+ template
+ inline bool
+ atomic_compare_exchange_weak(shared_ptr<_Tp>* __p, shared_ptr<_Tp>* __v,
+ shared_ptr<_Tp> __w)
+ {
+ return std::atomic_compare_exchange_weak_explicit(__p, __v,
+ std::move(__w), memory_order_seq_cst, memory_order_seq_cst);
+ }
+
+ template
+ bool
+ atomic_compare_exchange_strong_explicit(__shared_ptr<_Tp, _Lp>* __p,
+ __shared_ptr<_Tp, _Lp>* __v,
+ __shared_ptr<_Tp, _Lp> __w,
+ memory_order,
+ memory_order)
+ {
+ __shared_ptr<_Tp, _Lp> __x; // goes out of scope after __lock
+ _Sp_locker __lock{__p, __v};
+ owner_less<__shared_ptr<_Tp, _Lp>> __less;
+ if (*__p == *__v && !__less(*__p, *__v) && !__less(*__v, *__p))
+ {
+ __x = std::move(*__p);
+ *__p = std::move(__w);
+ return true;
+ }
+ __x = std::move(*__v);
+ *__v = *__p;
+ return false;
+ }
+
+ template
+ inline bool
+ atomic_compare_exchange_strong(__shared_ptr<_Tp, _Lp>* __p,
+ __shared_ptr<_Tp, _Lp>* __v,
+ __shared_ptr<_Tp, _Lp> __w)
+ {
+ return std::atomic_compare_exchange_strong_explicit(__p, __v,
+ std::move(__w), memory_order_seq_cst, memory_order_seq_cst);
+ }
+
+ template
+ inline bool
+ atomic_compare_exchange_weak_explicit(__shared_ptr<_Tp, _Lp>* __p,
+ __shared_ptr<_Tp, _Lp>* __v,
+ __shared_ptr<_Tp, _Lp> __w,
+ memory_order __success,
+ memory_order __failure)
+ {
+ return std::atomic_compare_exchange_strong_explicit(__p, __v,
+ std::move(__w), __success, __failure);
+ }
+
+ template
+ inline bool
+ atomic_compare_exchange_weak(__shared_ptr<_Tp, _Lp>* __p,
+ __shared_ptr<_Tp, _Lp>* __v,
+ __shared_ptr<_Tp, _Lp> __w)
+ {
+ return std::atomic_compare_exchange_weak_explicit(__p, __v,
+ std::move(__w), memory_order_seq_cst, memory_order_seq_cst);
+ }
+ // @}
+
+ // @} relates shared_ptr
+ // @} group pointer_abstractions
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif // _SHARED_PTR_ATOMIC_H
diff --git a/include/bits/shared_ptr_base.h b/include/bits/shared_ptr_base.h
new file mode 100644
index 0000000..ff578e6
--- /dev/null
+++ b/include/bits/shared_ptr_base.h
@@ -0,0 +1,1898 @@
+// shared_ptr and weak_ptr implementation details -*- C++ -*-
+
+// Copyright (C) 2007-2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// .
+
+// GCC Note: Based on files from version 1.32.0 of the Boost library.
+
+// shared_count.hpp
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+
+// shared_ptr.hpp
+// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
+// Copyright (C) 2001, 2002, 2003 Peter Dimov
+
+// weak_ptr.hpp
+// Copyright (C) 2001, 2002, 2003 Peter Dimov
+
+// enable_shared_from_this.hpp
+// Copyright (C) 2002 Peter Dimov
+
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/** @file bits/shared_ptr_base.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{memory}
+ */
+
+#ifndef _SHARED_PTR_BASE_H
+#define _SHARED_PTR_BASE_H 1
+
+#include
+#include
+#include
+#include
+#include
+#if __cplusplus > 201703L
+# include
+#endif
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+#if _GLIBCXX_USE_DEPRECATED
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ template class auto_ptr;
+#pragma GCC diagnostic pop
+#endif
+
+ /**
+ * @brief Exception possibly thrown by @c shared_ptr.
+ * @ingroup exceptions
+ */
+ class bad_weak_ptr : public std::exception
+ {
+ public:
+ virtual char const* what() const noexcept;
+
+ virtual ~bad_weak_ptr() noexcept;
+ };
+
+ // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
+ inline void
+ __throw_bad_weak_ptr()
+ { _GLIBCXX_THROW_OR_ABORT(bad_weak_ptr()); }
+
+ using __gnu_cxx::_Lock_policy;
+ using __gnu_cxx::__default_lock_policy;
+ using __gnu_cxx::_S_single;
+ using __gnu_cxx::_S_mutex;
+ using __gnu_cxx::_S_atomic;
+
+ // Empty helper class except when the template argument is _S_mutex.
+ template<_Lock_policy _Lp>
+ class _Mutex_base
+ {
+ protected:
+ // The atomic policy uses fully-fenced builtins, single doesn't care.
+ enum { _S_need_barriers = 0 };
+ };
+
+ template<>
+ class _Mutex_base<_S_mutex>
+ : public __gnu_cxx::__mutex
+ {
+ protected:
+ // This policy is used when atomic builtins are not available.
+ // The replacement atomic operations might not have the necessary
+ // memory barriers.
+ enum { _S_need_barriers = 1 };
+ };
+
+ template<_Lock_policy _Lp = __default_lock_policy>
+ class _Sp_counted_base
+ : public _Mutex_base<_Lp>
+ {
+ public:
+ _Sp_counted_base() noexcept
+ : _M_use_count(1), _M_weak_count(1) { }
+
+ virtual
+ ~_Sp_counted_base() noexcept
+ { }
+
+ // Called when _M_use_count drops to zero, to release the resources
+ // managed by *this.
+ virtual void
+ _M_dispose() noexcept = 0;
+
+ // Called when _M_weak_count drops to zero.
+ virtual void
+ _M_destroy() noexcept
+ { delete this; }
+
+ virtual void*
+ _M_get_deleter(const std::type_info&) noexcept = 0;
+
+ void
+ _M_add_ref_copy()
+ { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
+
+ void
+ _M_add_ref_lock();
+
+ bool
+ _M_add_ref_lock_nothrow();
+
+ void
+ _M_release() noexcept
+ {
+ // Be race-detector-friendly. For more info see bits/c++config.
+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
+ if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
+ {
+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
+ _M_dispose();
+ // There must be a memory barrier between dispose() and destroy()
+ // to ensure that the effects of dispose() are observed in the
+ // thread that runs destroy().
+ // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
+ if (_Mutex_base<_Lp>::_S_need_barriers)
+ {
+ __atomic_thread_fence (__ATOMIC_ACQ_REL);
+ }
+
+ // Be race-detector-friendly. For more info see bits/c++config.
+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
+ if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
+ -1) == 1)
+ {
+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
+ _M_destroy();
+ }
+ }
+ }
+
+ void
+ _M_weak_add_ref() noexcept
+ { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
+
+ void
+ _M_weak_release() noexcept
+ {
+ // Be race-detector-friendly. For more info see bits/c++config.
+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
+ if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
+ {
+ _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
+ if (_Mutex_base<_Lp>::_S_need_barriers)
+ {
+ // See _M_release(),
+ // destroy() must observe results of dispose()
+ __atomic_thread_fence (__ATOMIC_ACQ_REL);
+ }
+ _M_destroy();
+ }
+ }
+
+ long
+ _M_get_use_count() const noexcept
+ {
+ // No memory barrier is used here so there is no synchronization
+ // with other threads.
+ return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED);
+ }
+
+ private:
+ _Sp_counted_base(_Sp_counted_base const&) = delete;
+ _Sp_counted_base& operator=(_Sp_counted_base const&) = delete;
+
+ _Atomic_word _M_use_count; // #shared
+ _Atomic_word _M_weak_count; // #weak + (#shared != 0)
+ };
+
+ template<>
+ inline void
+ _Sp_counted_base<_S_single>::
+ _M_add_ref_lock()
+ {
+ if (_M_use_count == 0)
+ __throw_bad_weak_ptr();
+ ++_M_use_count;
+ }
+
+ template<>
+ inline void
+ _Sp_counted_base<_S_mutex>::
+ _M_add_ref_lock()
+ {
+ __gnu_cxx::__scoped_lock sentry(*this);
+ if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
+ {
+ _M_use_count = 0;
+ __throw_bad_weak_ptr();
+ }
+ }
+
+ template<>
+ inline void
+ _Sp_counted_base<_S_atomic>::
+ _M_add_ref_lock()
+ {
+ // Perform lock-free add-if-not-zero operation.
+ _Atomic_word __count = _M_get_use_count();
+ do
+ {
+ if (__count == 0)
+ __throw_bad_weak_ptr();
+ // Replace the current counter value with the old value + 1, as
+ // long as it's not changed meanwhile.
+ }
+ while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
+ true, __ATOMIC_ACQ_REL,
+ __ATOMIC_RELAXED));
+ }
+
+ template<>
+ inline bool
+ _Sp_counted_base<_S_single>::
+ _M_add_ref_lock_nothrow()
+ {
+ if (_M_use_count == 0)
+ return false;
+ ++_M_use_count;
+ return true;
+ }
+
+ template<>
+ inline bool
+ _Sp_counted_base<_S_mutex>::
+ _M_add_ref_lock_nothrow()
+ {
+ __gnu_cxx::__scoped_lock sentry(*this);
+ if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
+ {
+ _M_use_count = 0;
+ return false;
+ }
+ return true;
+ }
+
+ template<>
+ inline bool
+ _Sp_counted_base<_S_atomic>::
+ _M_add_ref_lock_nothrow()
+ {
+ // Perform lock-free add-if-not-zero operation.
+ _Atomic_word __count = _M_get_use_count();
+ do
+ {
+ if (__count == 0)
+ return false;
+ // Replace the current counter value with the old value + 1, as
+ // long as it's not changed meanwhile.
+ }
+ while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
+ true, __ATOMIC_ACQ_REL,
+ __ATOMIC_RELAXED));
+ return true;
+ }
+
+ template<>
+ inline void
+ _Sp_counted_base<_S_single>::_M_add_ref_copy()
+ { ++_M_use_count; }
+
+ template<>
+ inline void
+ _Sp_counted_base<_S_single>::_M_release() noexcept
+ {
+ if (--_M_use_count == 0)
+ {
+ _M_dispose();
+ if (--_M_weak_count == 0)
+ _M_destroy();
+ }
+ }
+
+ template<>
+ inline void
+ _Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept
+ { ++_M_weak_count; }
+
+ template<>
+ inline void
+ _Sp_counted_base<_S_single>::_M_weak_release() noexcept
+ {
+ if (--_M_weak_count == 0)
+ _M_destroy();
+ }
+
+ template<>
+ inline long
+ _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept
+ { return _M_use_count; }
+
+
+ // Forward declarations.
+ template
+ class __shared_ptr;
+
+ template
+ class __weak_ptr;
+
+ template
+ class __enable_shared_from_this;
+
+ template
+ class shared_ptr;
+
+ template
+ class weak_ptr;
+
+ template
+ struct owner_less;
+
+ template
+ class enable_shared_from_this;
+
+ template<_Lock_policy _Lp = __default_lock_policy>
+ class __weak_count;
+
+ template<_Lock_policy _Lp = __default_lock_policy>
+ class __shared_count;
+
+
+ // Counted ptr with no deleter or allocator support
+ template
+ class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>
+ {
+ public:
+ explicit
+ _Sp_counted_ptr(_Ptr __p) noexcept
+ : _M_ptr(__p) { }
+
+ virtual void
+ _M_dispose() noexcept
+ { delete _M_ptr; }
+
+ virtual void
+ _M_destroy() noexcept
+ { delete this; }
+
+ virtual void*
+ _M_get_deleter(const std::type_info&) noexcept
+ { return nullptr; }
+
+ _Sp_counted_ptr(const _Sp_counted_ptr&) = delete;
+ _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete;
+
+ private:
+ _Ptr _M_ptr;
+ };
+
+ template<>
+ inline void
+ _Sp_counted_ptr::_M_dispose() noexcept { }
+
+ template<>
+ inline void
+ _Sp_counted_ptr::_M_dispose() noexcept { }
+
+ template<>
+ inline void
+ _Sp_counted_ptr::_M_dispose() noexcept { }
+
+ template
+ struct _Sp_ebo_helper;
+
+ /// Specialization using EBO.
+ template
+ struct _Sp_ebo_helper<_Nm, _Tp, true> : private _Tp
+ {
+ explicit _Sp_ebo_helper(const _Tp& __tp) : _Tp(__tp) { }
+ explicit _Sp_ebo_helper(_Tp&& __tp) : _Tp(std::move(__tp)) { }
+
+ static _Tp&
+ _S_get(_Sp_ebo_helper& __eboh) { return static_cast<_Tp&>(__eboh); }
+ };
+
+ /// Specialization not using EBO.
+ template
+ struct _Sp_ebo_helper<_Nm, _Tp, false>
+ {
+ explicit _Sp_ebo_helper(const _Tp& __tp) : _M_tp(__tp) { }
+ explicit _Sp_ebo_helper(_Tp&& __tp) : _M_tp(std::move(__tp)) { }
+
+ static _Tp&
+ _S_get(_Sp_ebo_helper& __eboh)
+ { return __eboh._M_tp; }
+
+ private:
+ _Tp _M_tp;
+ };
+
+ // Support for custom deleter and/or allocator
+ template
+ class _Sp_counted_deleter final : public _Sp_counted_base<_Lp>
+ {
+ class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc>
+ {
+ typedef _Sp_ebo_helper<0, _Deleter> _Del_base;
+ typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base;
+
+ public:
+ _Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
+ : _M_ptr(__p), _Del_base(std::move(__d)), _Alloc_base(__a)
+ { }
+
+ _Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); }
+ _Alloc& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); }
+
+ _Ptr _M_ptr;
+ };
+
+ public:
+ using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_deleter>;
+
+ // __d(__p) must not throw.
+ _Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept
+ : _M_impl(__p, std::move(__d), _Alloc()) { }
+
+ // __d(__p) must not throw.
+ _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
+ : _M_impl(__p, std::move(__d), __a) { }
+
+ ~_Sp_counted_deleter() noexcept { }
+
+ virtual void
+ _M_dispose() noexcept
+ { _M_impl._M_del()(_M_impl._M_ptr); }
+
+ virtual void
+ _M_destroy() noexcept
+ {
+ __allocator_type __a(_M_impl._M_alloc());
+ __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
+ this->~_Sp_counted_deleter();
+ }
+
+ virtual void*
+ _M_get_deleter(const std::type_info& __ti) noexcept
+ {
+#if __cpp_rtti
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2400. shared_ptr's get_deleter() should use addressof()
+ return __ti == typeid(_Deleter)
+ ? std::__addressof(_M_impl._M_del())
+ : nullptr;
+#else
+ return nullptr;
+#endif
+ }
+
+ private:
+ _Impl _M_impl;
+ };
+
+ // helpers for make_shared / allocate_shared
+
+ struct _Sp_make_shared_tag
+ {
+ private:
+ template
+ friend class _Sp_counted_ptr_inplace;
+
+ static const type_info&
+ _S_ti() noexcept _GLIBCXX_VISIBILITY(default)
+ {
+ alignas(type_info) static constexpr char __tag[sizeof(type_info)] = { };
+ return reinterpret_cast(__tag);
+ }
+
+ static bool _S_eq(const type_info&) noexcept;
+ };
+
+ template
+ struct _Sp_alloc_shared_tag
+ {
+ const _Alloc& _M_a;
+ };
+
+ template
+ class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp>
+ {
+ class _Impl : _Sp_ebo_helper<0, _Alloc>
+ {
+ typedef _Sp_ebo_helper<0, _Alloc> _A_base;
+
+ public:
+ explicit _Impl(_Alloc __a) noexcept : _A_base(__a) { }
+
+ _Alloc& _M_alloc() noexcept { return _A_base::_S_get(*this); }
+
+ __gnu_cxx::__aligned_buffer<_Tp> _M_storage;
+ };
+
+ public:
+ using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>;
+
+ // Alloc parameter is not a reference so doesn't alias anything in __args
+ template
+ _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args)
+ : _M_impl(__a)
+ {
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2070. allocate_shared should use allocator_traits::construct
+ allocator_traits<_Alloc>::construct(__a, _M_ptr(),
+ std::forward<_Args>(__args)...); // might throw
+ }
+
+ ~_Sp_counted_ptr_inplace() noexcept { }
+
+ virtual void
+ _M_dispose() noexcept
+ {
+ allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr());
+ }
+
+ // Override because the allocator needs to know the dynamic type
+ virtual void
+ _M_destroy() noexcept
+ {
+ __allocator_type __a(_M_impl._M_alloc());
+ __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
+ this->~_Sp_counted_ptr_inplace();
+ }
+
+ private:
+ friend class __shared_count<_Lp>; // To be able to call _M_ptr().
+
+ // No longer used, but code compiled against old libstdc++ headers
+ // might still call it from __shared_ptr ctor to get the pointer out.
+ virtual void*
+ _M_get_deleter(const std::type_info& __ti) noexcept override
+ {
+ auto __ptr = const_cast::type*>(_M_ptr());
+ // Check for the fake type_info first, so we don't try to access it
+ // as a real type_info object. Otherwise, check if it's the real
+ // type_info for this class. With RTTI enabled we can check directly,
+ // or call a library function to do it.
+ if (&__ti == &_Sp_make_shared_tag::_S_ti()
+ ||
+#if __cpp_rtti
+ __ti == typeid(_Sp_make_shared_tag)
+#else
+ _Sp_make_shared_tag::_S_eq(__ti)
+#endif
+ )
+ return __ptr;
+ return nullptr;
+ }
+
+ _Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); }
+
+ _Impl _M_impl;
+ };
+
+ // The default deleter for shared_ptr and shared_ptr.
+ struct __sp_array_delete
+ {
+ template
+ void operator()(_Yp* __p) const { delete[] __p; }
+ };
+
+ template<_Lock_policy _Lp>
+ class __shared_count
+ {
+ template
+ struct __not_alloc_shared_tag { using type = void; };
+
+ template
+ struct __not_alloc_shared_tag<_Sp_alloc_shared_tag<_Tp>> { };
+
+ public:
+ constexpr __shared_count() noexcept : _M_pi(0)
+ { }
+
+ template
+ explicit
+ __shared_count(_Ptr __p) : _M_pi(0)
+ {
+ __try
+ {
+ _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);
+ }
+ __catch(...)
+ {
+ delete __p;
+ __throw_exception_again;
+ }
+ }
+
+ template
+ __shared_count(_Ptr __p, /* is_array = */ false_type)
+ : __shared_count(__p)
+ { }
+
+ template
+ __shared_count(_Ptr __p, /* is_array = */ true_type)
+ : __shared_count(__p, __sp_array_delete{}, allocator())
+ { }
+
+ template::type>
+ __shared_count(_Ptr __p, _Deleter __d)
+ : __shared_count(__p, std::move(__d), allocator())
+ { }
+
+ template::type>
+ __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
+ {
+ typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
+ __try
+ {
+ typename _Sp_cd_type::__allocator_type __a2(__a);
+ auto __guard = std::__allocate_guarded(__a2);
+ _Sp_cd_type* __mem = __guard.get();
+ ::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a));
+ _M_pi = __mem;
+ __guard = nullptr;
+ }
+ __catch(...)
+ {
+ __d(__p); // Call _Deleter on __p.
+ __throw_exception_again;
+ }
+ }
+
+ template
+ __shared_count(_Tp*& __p, _Sp_alloc_shared_tag<_Alloc> __a,
+ _Args&&... __args)
+ {
+ typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;
+ typename _Sp_cp_type::__allocator_type __a2(__a._M_a);
+ auto __guard = std::__allocate_guarded(__a2);
+ _Sp_cp_type* __mem = __guard.get();
+ auto __pi = ::new (__mem)
+ _Sp_cp_type(__a._M_a, std::forward<_Args>(__args)...);
+ __guard = nullptr;
+ _M_pi = __pi;
+ __p = __pi->_M_ptr();
+ }
+
+#if _GLIBCXX_USE_DEPRECATED
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ // Special case for auto_ptr<_Tp> to provide the strong guarantee.
+ template
+ explicit
+ __shared_count(std::auto_ptr<_Tp>&& __r);
+#pragma GCC diagnostic pop
+#endif
+
+ // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee.
+ template
+ explicit
+ __shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0)
+ {
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2415. Inconsistency between unique_ptr and shared_ptr
+ if (__r.get() == nullptr)
+ return;
+
+ using _Ptr = typename unique_ptr<_Tp, _Del>::pointer;
+ using _Del2 = typename conditional::value,
+ reference_wrapper::type>,
+ _Del>::type;
+ using _Sp_cd_type
+ = _Sp_counted_deleter<_Ptr, _Del2, allocator, _Lp>;
+ using _Alloc = allocator<_Sp_cd_type>;
+ using _Alloc_traits = allocator_traits<_Alloc>;
+ _Alloc __a;
+ _Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1);
+ _Alloc_traits::construct(__a, __mem, __r.release(),
+ __r.get_deleter()); // non-throwing
+ _M_pi = __mem;
+ }
+
+ // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
+ explicit __shared_count(const __weak_count<_Lp>& __r);
+
+ // Does not throw if __r._M_get_use_count() == 0, caller must check.
+ explicit __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t);
+
+ ~__shared_count() noexcept
+ {
+ if (_M_pi != nullptr)
+ _M_pi->_M_release();
+ }
+
+ __shared_count(const __shared_count& __r) noexcept
+ : _M_pi(__r._M_pi)
+ {
+ if (_M_pi != 0)
+ _M_pi->_M_add_ref_copy();
+ }
+
+ __shared_count&
+ operator=(const __shared_count& __r) noexcept
+ {
+ _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
+ if (__tmp != _M_pi)
+ {
+ if (__tmp != 0)
+ __tmp->_M_add_ref_copy();
+ if (_M_pi != 0)
+ _M_pi->_M_release();
+ _M_pi = __tmp;
+ }
+ return *this;
+ }
+
+ void
+ _M_swap(__shared_count& __r) noexcept
+ {
+ _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
+ __r._M_pi = _M_pi;
+ _M_pi = __tmp;
+ }
+
+ long
+ _M_get_use_count() const noexcept
+ { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
+
+ bool
+ _M_unique() const noexcept
+ { return this->_M_get_use_count() == 1; }
+
+ void*
+ _M_get_deleter(const std::type_info& __ti) const noexcept
+ { return _M_pi ? _M_pi->_M_get_deleter(__ti) : nullptr; }
+
+ bool
+ _M_less(const __shared_count& __rhs) const noexcept
+ { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
+
+ bool
+ _M_less(const __weak_count<_Lp>& __rhs) const noexcept
+ { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
+
+ // Friend function injected into enclosing namespace and found by ADL
+ friend inline bool
+ operator==(const __shared_count& __a, const __shared_count& __b) noexcept
+ { return __a._M_pi == __b._M_pi; }
+
+ private:
+ friend class __weak_count<_Lp>;
+
+ _Sp_counted_base<_Lp>* _M_pi;
+ };
+
+
+ template<_Lock_policy _Lp>
+ class __weak_count
+ {
+ public:
+ constexpr __weak_count() noexcept : _M_pi(nullptr)
+ { }
+
+ __weak_count(const __shared_count<_Lp>& __r) noexcept
+ : _M_pi(__r._M_pi)
+ {
+ if (_M_pi != nullptr)
+ _M_pi->_M_weak_add_ref();
+ }
+
+ __weak_count(const __weak_count& __r) noexcept
+ : _M_pi(__r._M_pi)
+ {
+ if (_M_pi != nullptr)
+ _M_pi->_M_weak_add_ref();
+ }
+
+ __weak_count(__weak_count&& __r) noexcept
+ : _M_pi(__r._M_pi)
+ { __r._M_pi = nullptr; }
+
+ ~__weak_count() noexcept
+ {
+ if (_M_pi != nullptr)
+ _M_pi->_M_weak_release();
+ }
+
+ __weak_count&
+ operator=(const __shared_count<_Lp>& __r) noexcept
+ {
+ _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
+ if (__tmp != nullptr)
+ __tmp->_M_weak_add_ref();
+ if (_M_pi != nullptr)
+ _M_pi->_M_weak_release();
+ _M_pi = __tmp;
+ return *this;
+ }
+
+ __weak_count&
+ operator=(const __weak_count& __r) noexcept
+ {
+ _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
+ if (__tmp != nullptr)
+ __tmp->_M_weak_add_ref();
+ if (_M_pi != nullptr)
+ _M_pi->_M_weak_release();
+ _M_pi = __tmp;
+ return *this;
+ }
+
+ __weak_count&
+ operator=(__weak_count&& __r) noexcept
+ {
+ if (_M_pi != nullptr)
+ _M_pi->_M_weak_release();
+ _M_pi = __r._M_pi;
+ __r._M_pi = nullptr;
+ return *this;
+ }
+
+ void
+ _M_swap(__weak_count& __r) noexcept
+ {
+ _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
+ __r._M_pi = _M_pi;
+ _M_pi = __tmp;
+ }
+
+ long
+ _M_get_use_count() const noexcept
+ { return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; }
+
+ bool
+ _M_less(const __weak_count& __rhs) const noexcept
+ { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
+
+ bool
+ _M_less(const __shared_count<_Lp>& __rhs) const noexcept
+ { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
+
+ // Friend function injected into enclosing namespace and found by ADL
+ friend inline bool
+ operator==(const __weak_count& __a, const __weak_count& __b) noexcept
+ { return __a._M_pi == __b._M_pi; }
+
+ private:
+ friend class __shared_count<_Lp>;
+
+ _Sp_counted_base<_Lp>* _M_pi;
+ };
+
+ // Now that __weak_count is defined we can define this constructor:
+ template<_Lock_policy _Lp>
+ inline
+ __shared_count<_Lp>::__shared_count(const __weak_count<_Lp>& __r)
+ : _M_pi(__r._M_pi)
+ {
+ if (_M_pi != nullptr)
+ _M_pi->_M_add_ref_lock();
+ else
+ __throw_bad_weak_ptr();
+ }
+
+ // Now that __weak_count is defined we can define this constructor:
+ template<_Lock_policy _Lp>
+ inline
+ __shared_count<_Lp>::
+ __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t)
+ : _M_pi(__r._M_pi)
+ {
+ if (_M_pi != nullptr)
+ if (!_M_pi->_M_add_ref_lock_nothrow())
+ _M_pi = nullptr;
+ }
+
+#define __cpp_lib_shared_ptr_arrays 201611L
+
+ // Helper traits for shared_ptr of array:
+
+ // A pointer type Y* is said to be compatible with a pointer type T* when
+ // either Y* is convertible to T* or Y is U[N] and T is U cv [].
+ template
+ struct __sp_compatible_with
+ : false_type
+ { };
+
+ template
+ struct __sp_compatible_with<_Yp*, _Tp*>
+ : is_convertible<_Yp*, _Tp*>::type
+ { };
+
+ template
+ struct __sp_compatible_with<_Up(*)[_Nm], _Up(*)[]>
+ : true_type
+ { };
+
+ template
+ struct __sp_compatible_with<_Up(*)[_Nm], const _Up(*)[]>
+ : true_type
+ { };
+
+ template
+ struct __sp_compatible_with<_Up(*)[_Nm], volatile _Up(*)[]>
+ : true_type
+ { };
+
+ template
+ struct __sp_compatible_with<_Up(*)[_Nm], const volatile _Up(*)[]>
+ : true_type
+ { };
+
+ // Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N].
+ template
+ struct __sp_is_constructible_arrN
+ : false_type
+ { };
+
+ template
+ struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>>
+ : is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type
+ { };
+
+ // Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[].
+ template
+ struct __sp_is_constructible_arr
+ : false_type
+ { };
+
+ template
+ struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>>
+ : is_convertible<_Yp(*)[], _Up(*)[]>::type
+ { };
+
+ // Trait to check if shared_ptr can be constructed from Y*.
+ template
+ struct __sp_is_constructible;
+
+ // When T is U[N], Y(*)[N] shall be convertible to T*;
+ template
+ struct __sp_is_constructible<_Up[_Nm], _Yp>
+ : __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type
+ { };
+
+ // when T is U[], Y(*)[] shall be convertible to T*;
+ template
+ struct __sp_is_constructible<_Up[], _Yp>
+ : __sp_is_constructible_arr<_Up, _Yp>::type
+ { };
+
+ // otherwise, Y* shall be convertible to T*.
+ template
+ struct __sp_is_constructible
+ : is_convertible<_Yp*, _Tp*>::type
+ { };
+
+
+ // Define operator* and operator-> for shared_ptr.
+ template::value, bool = is_void<_Tp>::value>
+ class __shared_ptr_access
+ {
+ public:
+ using element_type = _Tp;
+
+ element_type&
+ operator*() const noexcept
+ {
+ __glibcxx_assert(_M_get() != nullptr);
+ return *_M_get();
+ }
+
+ element_type*
+ operator->() const noexcept
+ {
+ _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
+ return _M_get();
+ }
+
+ private:
+ element_type*
+ _M_get() const noexcept
+ { return static_cast*>(this)->get(); }
+ };
+
+ // Define operator-> for shared_ptr.
+ template
+ class __shared_ptr_access<_Tp, _Lp, false, true>
+ {
+ public:
+ using element_type = _Tp;
+
+ element_type*
+ operator->() const noexcept
+ {
+ auto __ptr = static_cast*>(this)->get();
+ _GLIBCXX_DEBUG_PEDASSERT(__ptr != nullptr);
+ return __ptr;
+ }
+ };
+
+ // Define operator[] for shared_ptr and shared_ptr.
+ template
+ class __shared_ptr_access<_Tp, _Lp, true, false>
+ {
+ public:
+ using element_type = typename remove_extent<_Tp>::type;
+
+#if __cplusplus <= 201402L
+ [[__deprecated__("shared_ptr::operator* is absent from C++17")]]
+ element_type&
+ operator*() const noexcept
+ {
+ __glibcxx_assert(_M_get() != nullptr);
+ return *_M_get();
+ }
+
+ [[__deprecated__("shared_ptr::operator-> is absent from C++17")]]
+ element_type*
+ operator->() const noexcept
+ {
+ _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
+ return _M_get();
+ }
+#endif
+
+ element_type&
+ operator[](ptrdiff_t __i) const
+ {
+ __glibcxx_assert(_M_get() != nullptr);
+ __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value);
+ return _M_get()[__i];
+ }
+
+ private:
+ element_type*
+ _M_get() const noexcept
+ { return static_cast*>(this)->get(); }
+ };
+
+ template
+ class __shared_ptr
+ : public __shared_ptr_access<_Tp, _Lp>
+ {
+ public:
+ using element_type = typename remove_extent<_Tp>::type;
+
+ private:
+ // Constraint for taking ownership of a pointer of type _Yp*:
+ template
+ using _SafeConv
+ = typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type;
+
+ // Constraint for construction from shared_ptr and weak_ptr:
+ template
+ using _Compatible = typename
+ enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
+
+ // Constraint for assignment from shared_ptr and weak_ptr:
+ template
+ using _Assignable = _Compatible<_Yp, __shared_ptr&>;
+
+ // Constraint for construction from unique_ptr:
+ template::pointer>
+ using _UniqCompatible = typename enable_if<__and_<
+ __sp_compatible_with<_Yp*, _Tp*>, is_convertible<_Ptr, element_type*>
+ >::value, _Res>::type;
+
+ // Constraint for assignment from unique_ptr:
+ template
+ using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>;
+
+ public:
+
+#if __cplusplus > 201402L
+ using weak_type = __weak_ptr<_Tp, _Lp>;
+#endif
+
+ constexpr __shared_ptr() noexcept
+ : _M_ptr(0), _M_refcount()
+ { }
+
+ template>
+ explicit
+ __shared_ptr(_Yp* __p)
+ : _M_ptr(__p), _M_refcount(__p, typename is_array<_Tp>::type())
+ {
+ static_assert( !is_void<_Yp>::value, "incomplete type" );
+ static_assert( sizeof(_Yp) > 0, "incomplete type" );
+ _M_enable_shared_from_this_with(__p);
+ }
+
+ template>
+ __shared_ptr(_Yp* __p, _Deleter __d)
+ : _M_ptr(__p), _M_refcount(__p, std::move(__d))
+ {
+ static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
+ "deleter expression d(p) is well-formed");
+ _M_enable_shared_from_this_with(__p);
+ }
+
+ template>
+ __shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
+ : _M_ptr(__p), _M_refcount(__p, std::move(__d), std::move(__a))
+ {
+ static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
+ "deleter expression d(p) is well-formed");
+ _M_enable_shared_from_this_with(__p);
+ }
+
+ template
+ __shared_ptr(nullptr_t __p, _Deleter __d)
+ : _M_ptr(0), _M_refcount(__p, std::move(__d))
+ { }
+
+ template
+ __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
+ : _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a))
+ { }
+
+ // Aliasing constructor
+ template
+ __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r,
+ element_type* __p) noexcept
+ : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
+ { }
+
+ // Aliasing constructor
+ template
+ __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r,
+ element_type* __p) noexcept
+ : _M_ptr(__p), _M_refcount()
+ {
+ _M_refcount._M_swap(__r._M_refcount);
+ __r._M_ptr = 0;
+ }
+
+ __shared_ptr(const __shared_ptr&) noexcept = default;
+ __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
+ ~__shared_ptr() = default;
+
+ template>
+ __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
+ : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
+ { }
+
+ __shared_ptr(__shared_ptr&& __r) noexcept
+ : _M_ptr(__r._M_ptr), _M_refcount()
+ {
+ _M_refcount._M_swap(__r._M_refcount);
+ __r._M_ptr = 0;
+ }
+
+ template>
+ __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept
+ : _M_ptr(__r._M_ptr), _M_refcount()
+ {
+ _M_refcount._M_swap(__r._M_refcount);
+ __r._M_ptr = 0;
+ }
+
+ template>
+ explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r)
+ : _M_refcount(__r._M_refcount) // may throw
+ {
+ // It is now safe to copy __r._M_ptr, as
+ // _M_refcount(__r._M_refcount) did not throw.
+ _M_ptr = __r._M_ptr;
+ }
+
+ // If an exception is thrown this constructor has no effect.
+ template>
+ __shared_ptr(unique_ptr<_Yp, _Del>&& __r)
+ : _M_ptr(__r.get()), _M_refcount()
+ {
+ auto __raw = __to_address(__r.get());
+ _M_refcount = __shared_count<_Lp>(std::move(__r));
+ _M_enable_shared_from_this_with(__raw);
+ }
+
+#if __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATED
+ protected:
+ // If an exception is thrown this constructor has no effect.
+ template>, is_array<_Tp1>,
+ is_convertible::pointer, _Tp*>
+ >::value, bool>::type = true>
+ __shared_ptr(unique_ptr<_Tp1, _Del>&& __r, __sp_array_delete)
+ : _M_ptr(__r.get()), _M_refcount()
+ {
+ auto __raw = __to_address(__r.get());
+ _M_refcount = __shared_count<_Lp>(std::move(__r));
+ _M_enable_shared_from_this_with(__raw);
+ }
+ public:
+#endif
+
+#if _GLIBCXX_USE_DEPRECATED
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ // Postcondition: use_count() == 1 and __r.get() == 0
+ template