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