libstdc++
|
00001 // shared_ptr and weak_ptr implementation details -*- C++ -*- 00002 00003 // Copyright (C) 2007-2019 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 // GCC Note: Based on files from version 1.32.0 of the Boost library. 00026 00027 // shared_count.hpp 00028 // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. 00029 00030 // shared_ptr.hpp 00031 // Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes. 00032 // Copyright (C) 2001, 2002, 2003 Peter Dimov 00033 00034 // weak_ptr.hpp 00035 // Copyright (C) 2001, 2002, 2003 Peter Dimov 00036 00037 // enable_shared_from_this.hpp 00038 // Copyright (C) 2002 Peter Dimov 00039 00040 // Distributed under the Boost Software License, Version 1.0. (See 00041 // accompanying file LICENSE_1_0.txt or copy at 00042 // http://www.boost.org/LICENSE_1_0.txt) 00043 00044 /** @file bits/shared_ptr_base.h 00045 * This is an internal header file, included by other library headers. 00046 * Do not attempt to use it directly. @headername{memory} 00047 */ 00048 00049 #ifndef _SHARED_PTR_BASE_H 00050 #define _SHARED_PTR_BASE_H 1 00051 00052 #include <typeinfo> 00053 #include <bits/allocated_ptr.h> 00054 #include <bits/refwrap.h> 00055 #include <bits/stl_function.h> 00056 #include <ext/aligned_buffer.h> 00057 00058 namespace std _GLIBCXX_VISIBILITY(default) 00059 { 00060 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00061 00062 #if _GLIBCXX_USE_DEPRECATED 00063 #pragma GCC diagnostic push 00064 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 00065 template<typename> class auto_ptr; 00066 #pragma GCC diagnostic pop 00067 #endif 00068 00069 /** 00070 * @brief Exception possibly thrown by @c shared_ptr. 00071 * @ingroup exceptions 00072 */ 00073 class bad_weak_ptr : public std::exception 00074 { 00075 public: 00076 virtual char const* what() const noexcept; 00077 00078 virtual ~bad_weak_ptr() noexcept; 00079 }; 00080 00081 // Substitute for bad_weak_ptr object in the case of -fno-exceptions. 00082 inline void 00083 __throw_bad_weak_ptr() 00084 { _GLIBCXX_THROW_OR_ABORT(bad_weak_ptr()); } 00085 00086 using __gnu_cxx::_Lock_policy; 00087 using __gnu_cxx::__default_lock_policy; 00088 using __gnu_cxx::_S_single; 00089 using __gnu_cxx::_S_mutex; 00090 using __gnu_cxx::_S_atomic; 00091 00092 // Empty helper class except when the template argument is _S_mutex. 00093 template<_Lock_policy _Lp> 00094 class _Mutex_base 00095 { 00096 protected: 00097 // The atomic policy uses fully-fenced builtins, single doesn't care. 00098 enum { _S_need_barriers = 0 }; 00099 }; 00100 00101 template<> 00102 class _Mutex_base<_S_mutex> 00103 : public __gnu_cxx::__mutex 00104 { 00105 protected: 00106 // This policy is used when atomic builtins are not available. 00107 // The replacement atomic operations might not have the necessary 00108 // memory barriers. 00109 enum { _S_need_barriers = 1 }; 00110 }; 00111 00112 template<_Lock_policy _Lp = __default_lock_policy> 00113 class _Sp_counted_base 00114 : public _Mutex_base<_Lp> 00115 { 00116 public: 00117 _Sp_counted_base() noexcept 00118 : _M_use_count(1), _M_weak_count(1) { } 00119 00120 virtual 00121 ~_Sp_counted_base() noexcept 00122 { } 00123 00124 // Called when _M_use_count drops to zero, to release the resources 00125 // managed by *this. 00126 virtual void 00127 _M_dispose() noexcept = 0; 00128 00129 // Called when _M_weak_count drops to zero. 00130 virtual void 00131 _M_destroy() noexcept 00132 { delete this; } 00133 00134 virtual void* 00135 _M_get_deleter(const std::type_info&) noexcept = 0; 00136 00137 void 00138 _M_add_ref_copy() 00139 { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); } 00140 00141 void 00142 _M_add_ref_lock(); 00143 00144 bool 00145 _M_add_ref_lock_nothrow(); 00146 00147 void 00148 _M_release() noexcept 00149 { 00150 // Be race-detector-friendly. For more info see bits/c++config. 00151 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count); 00152 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1) 00153 { 00154 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count); 00155 _M_dispose(); 00156 // There must be a memory barrier between dispose() and destroy() 00157 // to ensure that the effects of dispose() are observed in the 00158 // thread that runs destroy(). 00159 // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html 00160 if (_Mutex_base<_Lp>::_S_need_barriers) 00161 { 00162 __atomic_thread_fence (__ATOMIC_ACQ_REL); 00163 } 00164 00165 // Be race-detector-friendly. For more info see bits/c++config. 00166 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count); 00167 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, 00168 -1) == 1) 00169 { 00170 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count); 00171 _M_destroy(); 00172 } 00173 } 00174 } 00175 00176 void 00177 _M_weak_add_ref() noexcept 00178 { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); } 00179 00180 void 00181 _M_weak_release() noexcept 00182 { 00183 // Be race-detector-friendly. For more info see bits/c++config. 00184 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count); 00185 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1) 00186 { 00187 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count); 00188 if (_Mutex_base<_Lp>::_S_need_barriers) 00189 { 00190 // See _M_release(), 00191 // destroy() must observe results of dispose() 00192 __atomic_thread_fence (__ATOMIC_ACQ_REL); 00193 } 00194 _M_destroy(); 00195 } 00196 } 00197 00198 long 00199 _M_get_use_count() const noexcept 00200 { 00201 // No memory barrier is used here so there is no synchronization 00202 // with other threads. 00203 return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED); 00204 } 00205 00206 private: 00207 _Sp_counted_base(_Sp_counted_base const&) = delete; 00208 _Sp_counted_base& operator=(_Sp_counted_base const&) = delete; 00209 00210 _Atomic_word _M_use_count; // #shared 00211 _Atomic_word _M_weak_count; // #weak + (#shared != 0) 00212 }; 00213 00214 template<> 00215 inline void 00216 _Sp_counted_base<_S_single>:: 00217 _M_add_ref_lock() 00218 { 00219 if (_M_use_count == 0) 00220 __throw_bad_weak_ptr(); 00221 ++_M_use_count; 00222 } 00223 00224 template<> 00225 inline void 00226 _Sp_counted_base<_S_mutex>:: 00227 _M_add_ref_lock() 00228 { 00229 __gnu_cxx::__scoped_lock sentry(*this); 00230 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0) 00231 { 00232 _M_use_count = 0; 00233 __throw_bad_weak_ptr(); 00234 } 00235 } 00236 00237 template<> 00238 inline void 00239 _Sp_counted_base<_S_atomic>:: 00240 _M_add_ref_lock() 00241 { 00242 // Perform lock-free add-if-not-zero operation. 00243 _Atomic_word __count = _M_get_use_count(); 00244 do 00245 { 00246 if (__count == 0) 00247 __throw_bad_weak_ptr(); 00248 // Replace the current counter value with the old value + 1, as 00249 // long as it's not changed meanwhile. 00250 } 00251 while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1, 00252 true, __ATOMIC_ACQ_REL, 00253 __ATOMIC_RELAXED)); 00254 } 00255 00256 template<> 00257 inline bool 00258 _Sp_counted_base<_S_single>:: 00259 _M_add_ref_lock_nothrow() 00260 { 00261 if (_M_use_count == 0) 00262 return false; 00263 ++_M_use_count; 00264 return true; 00265 } 00266 00267 template<> 00268 inline bool 00269 _Sp_counted_base<_S_mutex>:: 00270 _M_add_ref_lock_nothrow() 00271 { 00272 __gnu_cxx::__scoped_lock sentry(*this); 00273 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0) 00274 { 00275 _M_use_count = 0; 00276 return false; 00277 } 00278 return true; 00279 } 00280 00281 template<> 00282 inline bool 00283 _Sp_counted_base<_S_atomic>:: 00284 _M_add_ref_lock_nothrow() 00285 { 00286 // Perform lock-free add-if-not-zero operation. 00287 _Atomic_word __count = _M_get_use_count(); 00288 do 00289 { 00290 if (__count == 0) 00291 return false; 00292 // Replace the current counter value with the old value + 1, as 00293 // long as it's not changed meanwhile. 00294 } 00295 while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1, 00296 true, __ATOMIC_ACQ_REL, 00297 __ATOMIC_RELAXED)); 00298 return true; 00299 } 00300 00301 template<> 00302 inline void 00303 _Sp_counted_base<_S_single>::_M_add_ref_copy() 00304 { ++_M_use_count; } 00305 00306 template<> 00307 inline void 00308 _Sp_counted_base<_S_single>::_M_release() noexcept 00309 { 00310 if (--_M_use_count == 0) 00311 { 00312 _M_dispose(); 00313 if (--_M_weak_count == 0) 00314 _M_destroy(); 00315 } 00316 } 00317 00318 template<> 00319 inline void 00320 _Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept 00321 { ++_M_weak_count; } 00322 00323 template<> 00324 inline void 00325 _Sp_counted_base<_S_single>::_M_weak_release() noexcept 00326 { 00327 if (--_M_weak_count == 0) 00328 _M_destroy(); 00329 } 00330 00331 template<> 00332 inline long 00333 _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept 00334 { return _M_use_count; } 00335 00336 00337 // Forward declarations. 00338 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> 00339 class __shared_ptr; 00340 00341 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> 00342 class __weak_ptr; 00343 00344 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> 00345 class __enable_shared_from_this; 00346 00347 template<typename _Tp> 00348 class shared_ptr; 00349 00350 template<typename _Tp> 00351 class weak_ptr; 00352 00353 template<typename _Tp> 00354 struct owner_less; 00355 00356 template<typename _Tp> 00357 class enable_shared_from_this; 00358 00359 template<_Lock_policy _Lp = __default_lock_policy> 00360 class __weak_count; 00361 00362 template<_Lock_policy _Lp = __default_lock_policy> 00363 class __shared_count; 00364 00365 00366 // Counted ptr with no deleter or allocator support 00367 template<typename _Ptr, _Lock_policy _Lp> 00368 class _Sp_counted_ptr final : public _Sp_counted_base<_Lp> 00369 { 00370 public: 00371 explicit 00372 _Sp_counted_ptr(_Ptr __p) noexcept 00373 : _M_ptr(__p) { } 00374 00375 virtual void 00376 _M_dispose() noexcept 00377 { delete _M_ptr; } 00378 00379 virtual void 00380 _M_destroy() noexcept 00381 { delete this; } 00382 00383 virtual void* 00384 _M_get_deleter(const std::type_info&) noexcept 00385 { return nullptr; } 00386 00387 _Sp_counted_ptr(const _Sp_counted_ptr&) = delete; 00388 _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete; 00389 00390 private: 00391 _Ptr _M_ptr; 00392 }; 00393 00394 template<> 00395 inline void 00396 _Sp_counted_ptr<nullptr_t, _S_single>::_M_dispose() noexcept { } 00397 00398 template<> 00399 inline void 00400 _Sp_counted_ptr<nullptr_t, _S_mutex>::_M_dispose() noexcept { } 00401 00402 template<> 00403 inline void 00404 _Sp_counted_ptr<nullptr_t, _S_atomic>::_M_dispose() noexcept { } 00405 00406 template<int _Nm, typename _Tp, 00407 bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)> 00408 struct _Sp_ebo_helper; 00409 00410 /// Specialization using EBO. 00411 template<int _Nm, typename _Tp> 00412 struct _Sp_ebo_helper<_Nm, _Tp, true> : private _Tp 00413 { 00414 explicit _Sp_ebo_helper(const _Tp& __tp) : _Tp(__tp) { } 00415 explicit _Sp_ebo_helper(_Tp&& __tp) : _Tp(std::move(__tp)) { } 00416 00417 static _Tp& 00418 _S_get(_Sp_ebo_helper& __eboh) { return static_cast<_Tp&>(__eboh); } 00419 }; 00420 00421 /// Specialization not using EBO. 00422 template<int _Nm, typename _Tp> 00423 struct _Sp_ebo_helper<_Nm, _Tp, false> 00424 { 00425 explicit _Sp_ebo_helper(const _Tp& __tp) : _M_tp(__tp) { } 00426 explicit _Sp_ebo_helper(_Tp&& __tp) : _M_tp(std::move(__tp)) { } 00427 00428 static _Tp& 00429 _S_get(_Sp_ebo_helper& __eboh) 00430 { return __eboh._M_tp; } 00431 00432 private: 00433 _Tp _M_tp; 00434 }; 00435 00436 // Support for custom deleter and/or allocator 00437 template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp> 00438 class _Sp_counted_deleter final : public _Sp_counted_base<_Lp> 00439 { 00440 class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc> 00441 { 00442 typedef _Sp_ebo_helper<0, _Deleter> _Del_base; 00443 typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base; 00444 00445 public: 00446 _Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept 00447 : _M_ptr(__p), _Del_base(std::move(__d)), _Alloc_base(__a) 00448 { } 00449 00450 _Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); } 00451 _Alloc& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); } 00452 00453 _Ptr _M_ptr; 00454 }; 00455 00456 public: 00457 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_deleter>; 00458 00459 // __d(__p) must not throw. 00460 _Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept 00461 : _M_impl(__p, std::move(__d), _Alloc()) { } 00462 00463 // __d(__p) must not throw. 00464 _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept 00465 : _M_impl(__p, std::move(__d), __a) { } 00466 00467 ~_Sp_counted_deleter() noexcept { } 00468 00469 virtual void 00470 _M_dispose() noexcept 00471 { _M_impl._M_del()(_M_impl._M_ptr); } 00472 00473 virtual void 00474 _M_destroy() noexcept 00475 { 00476 __allocator_type __a(_M_impl._M_alloc()); 00477 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this }; 00478 this->~_Sp_counted_deleter(); 00479 } 00480 00481 virtual void* 00482 _M_get_deleter(const std::type_info& __ti) noexcept 00483 { 00484 #if __cpp_rtti 00485 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00486 // 2400. shared_ptr's get_deleter() should use addressof() 00487 return __ti == typeid(_Deleter) 00488 ? std::__addressof(_M_impl._M_del()) 00489 : nullptr; 00490 #else 00491 return nullptr; 00492 #endif 00493 } 00494 00495 private: 00496 _Impl _M_impl; 00497 }; 00498 00499 // helpers for make_shared / allocate_shared 00500 00501 struct _Sp_make_shared_tag 00502 { 00503 private: 00504 template<typename _Tp, typename _Alloc, _Lock_policy _Lp> 00505 friend class _Sp_counted_ptr_inplace; 00506 00507 static const type_info& 00508 _S_ti() noexcept _GLIBCXX_VISIBILITY(default) 00509 { 00510 alignas(type_info) static constexpr char __tag[sizeof(type_info)] = { }; 00511 return reinterpret_cast<const type_info&>(__tag); 00512 } 00513 00514 static bool _S_eq(const type_info&) noexcept; 00515 }; 00516 00517 template<typename _Alloc> 00518 struct _Sp_alloc_shared_tag 00519 { 00520 const _Alloc& _M_a; 00521 }; 00522 00523 template<typename _Tp, typename _Alloc, _Lock_policy _Lp> 00524 class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp> 00525 { 00526 class _Impl : _Sp_ebo_helper<0, _Alloc> 00527 { 00528 typedef _Sp_ebo_helper<0, _Alloc> _A_base; 00529 00530 public: 00531 explicit _Impl(_Alloc __a) noexcept : _A_base(__a) { } 00532 00533 _Alloc& _M_alloc() noexcept { return _A_base::_S_get(*this); } 00534 00535 __gnu_cxx::__aligned_buffer<_Tp> _M_storage; 00536 }; 00537 00538 public: 00539 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>; 00540 00541 // Alloc parameter is not a reference so doesn't alias anything in __args 00542 template<typename... _Args> 00543 _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args) 00544 : _M_impl(__a) 00545 { 00546 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00547 // 2070. allocate_shared should use allocator_traits<A>::construct 00548 allocator_traits<_Alloc>::construct(__a, _M_ptr(), 00549 std::forward<_Args>(__args)...); // might throw 00550 } 00551 00552 ~_Sp_counted_ptr_inplace() noexcept { } 00553 00554 virtual void 00555 _M_dispose() noexcept 00556 { 00557 allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr()); 00558 } 00559 00560 // Override because the allocator needs to know the dynamic type 00561 virtual void 00562 _M_destroy() noexcept 00563 { 00564 __allocator_type __a(_M_impl._M_alloc()); 00565 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this }; 00566 this->~_Sp_counted_ptr_inplace(); 00567 } 00568 00569 private: 00570 friend class __shared_count<_Lp>; // To be able to call _M_ptr(). 00571 00572 // No longer used, but code compiled against old libstdc++ headers 00573 // might still call it from __shared_ptr ctor to get the pointer out. 00574 virtual void* 00575 _M_get_deleter(const std::type_info& __ti) noexcept override 00576 { 00577 auto __ptr = const_cast<typename remove_cv<_Tp>::type*>(_M_ptr()); 00578 // Check for the fake type_info first, so we don't try to access it 00579 // as a real type_info object. Otherwise, check if it's the real 00580 // type_info for this class. With RTTI enabled we can check directly, 00581 // or call a library function to do it. 00582 if (&__ti == &_Sp_make_shared_tag::_S_ti() 00583 || 00584 #if __cpp_rtti 00585 __ti == typeid(_Sp_make_shared_tag) 00586 #else 00587 _Sp_make_shared_tag::_S_eq(__ti) 00588 #endif 00589 ) 00590 return __ptr; 00591 return nullptr; 00592 } 00593 00594 _Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); } 00595 00596 _Impl _M_impl; 00597 }; 00598 00599 // The default deleter for shared_ptr<T[]> and shared_ptr<T[N]>. 00600 struct __sp_array_delete 00601 { 00602 template<typename _Yp> 00603 void operator()(_Yp* __p) const { delete[] __p; } 00604 }; 00605 00606 template<_Lock_policy _Lp> 00607 class __shared_count 00608 { 00609 template<typename _Tp> 00610 struct __not_alloc_shared_tag { using type = void; }; 00611 00612 template<typename _Tp> 00613 struct __not_alloc_shared_tag<_Sp_alloc_shared_tag<_Tp>> { }; 00614 00615 public: 00616 constexpr __shared_count() noexcept : _M_pi(0) 00617 { } 00618 00619 template<typename _Ptr> 00620 explicit 00621 __shared_count(_Ptr __p) : _M_pi(0) 00622 { 00623 __try 00624 { 00625 _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p); 00626 } 00627 __catch(...) 00628 { 00629 delete __p; 00630 __throw_exception_again; 00631 } 00632 } 00633 00634 template<typename _Ptr> 00635 __shared_count(_Ptr __p, /* is_array = */ false_type) 00636 : __shared_count(__p) 00637 { } 00638 00639 template<typename _Ptr> 00640 __shared_count(_Ptr __p, /* is_array = */ true_type) 00641 : __shared_count(__p, __sp_array_delete{}, allocator<void>()) 00642 { } 00643 00644 template<typename _Ptr, typename _Deleter, 00645 typename = typename __not_alloc_shared_tag<_Deleter>::type> 00646 __shared_count(_Ptr __p, _Deleter __d) 00647 : __shared_count(__p, std::move(__d), allocator<void>()) 00648 { } 00649 00650 template<typename _Ptr, typename _Deleter, typename _Alloc, 00651 typename = typename __not_alloc_shared_tag<_Deleter>::type> 00652 __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0) 00653 { 00654 typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type; 00655 __try 00656 { 00657 typename _Sp_cd_type::__allocator_type __a2(__a); 00658 auto __guard = std::__allocate_guarded(__a2); 00659 _Sp_cd_type* __mem = __guard.get(); 00660 ::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a)); 00661 _M_pi = __mem; 00662 __guard = nullptr; 00663 } 00664 __catch(...) 00665 { 00666 __d(__p); // Call _Deleter on __p. 00667 __throw_exception_again; 00668 } 00669 } 00670 00671 template<typename _Tp, typename _Alloc, typename... _Args> 00672 __shared_count(_Tp*& __p, _Sp_alloc_shared_tag<_Alloc> __a, 00673 _Args&&... __args) 00674 { 00675 typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type; 00676 typename _Sp_cp_type::__allocator_type __a2(__a._M_a); 00677 auto __guard = std::__allocate_guarded(__a2); 00678 _Sp_cp_type* __mem = __guard.get(); 00679 auto __pi = ::new (__mem) 00680 _Sp_cp_type(__a._M_a, std::forward<_Args>(__args)...); 00681 __guard = nullptr; 00682 _M_pi = __pi; 00683 __p = __pi->_M_ptr(); 00684 } 00685 00686 #if _GLIBCXX_USE_DEPRECATED 00687 #pragma GCC diagnostic push 00688 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 00689 // Special case for auto_ptr<_Tp> to provide the strong guarantee. 00690 template<typename _Tp> 00691 explicit 00692 __shared_count(std::auto_ptr<_Tp>&& __r); 00693 #pragma GCC diagnostic pop 00694 #endif 00695 00696 // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee. 00697 template<typename _Tp, typename _Del> 00698 explicit 00699 __shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0) 00700 { 00701 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00702 // 2415. Inconsistency between unique_ptr and shared_ptr 00703 if (__r.get() == nullptr) 00704 return; 00705 00706 using _Ptr = typename unique_ptr<_Tp, _Del>::pointer; 00707 using _Del2 = typename conditional<is_reference<_Del>::value, 00708 reference_wrapper<typename remove_reference<_Del>::type>, 00709 _Del>::type; 00710 using _Sp_cd_type 00711 = _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>; 00712 using _Alloc = allocator<_Sp_cd_type>; 00713 using _Alloc_traits = allocator_traits<_Alloc>; 00714 _Alloc __a; 00715 _Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1); 00716 _Alloc_traits::construct(__a, __mem, __r.release(), 00717 __r.get_deleter()); // non-throwing 00718 _M_pi = __mem; 00719 } 00720 00721 // Throw bad_weak_ptr when __r._M_get_use_count() == 0. 00722 explicit __shared_count(const __weak_count<_Lp>& __r); 00723 00724 // Does not throw if __r._M_get_use_count() == 0, caller must check. 00725 explicit __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t); 00726 00727 ~__shared_count() noexcept 00728 { 00729 if (_M_pi != nullptr) 00730 _M_pi->_M_release(); 00731 } 00732 00733 __shared_count(const __shared_count& __r) noexcept 00734 : _M_pi(__r._M_pi) 00735 { 00736 if (_M_pi != 0) 00737 _M_pi->_M_add_ref_copy(); 00738 } 00739 00740 __shared_count& 00741 operator=(const __shared_count& __r) noexcept 00742 { 00743 _Sp_counted_base<_Lp>* __tmp = __r._M_pi; 00744 if (__tmp != _M_pi) 00745 { 00746 if (__tmp != 0) 00747 __tmp->_M_add_ref_copy(); 00748 if (_M_pi != 0) 00749 _M_pi->_M_release(); 00750 _M_pi = __tmp; 00751 } 00752 return *this; 00753 } 00754 00755 void 00756 _M_swap(__shared_count& __r) noexcept 00757 { 00758 _Sp_counted_base<_Lp>* __tmp = __r._M_pi; 00759 __r._M_pi = _M_pi; 00760 _M_pi = __tmp; 00761 } 00762 00763 long 00764 _M_get_use_count() const noexcept 00765 { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; } 00766 00767 bool 00768 _M_unique() const noexcept 00769 { return this->_M_get_use_count() == 1; } 00770 00771 void* 00772 _M_get_deleter(const std::type_info& __ti) const noexcept 00773 { return _M_pi ? _M_pi->_M_get_deleter(__ti) : nullptr; } 00774 00775 bool 00776 _M_less(const __shared_count& __rhs) const noexcept 00777 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } 00778 00779 bool 00780 _M_less(const __weak_count<_Lp>& __rhs) const noexcept 00781 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } 00782 00783 // Friend function injected into enclosing namespace and found by ADL 00784 friend inline bool 00785 operator==(const __shared_count& __a, const __shared_count& __b) noexcept 00786 { return __a._M_pi == __b._M_pi; } 00787 00788 private: 00789 friend class __weak_count<_Lp>; 00790 00791 _Sp_counted_base<_Lp>* _M_pi; 00792 }; 00793 00794 00795 template<_Lock_policy _Lp> 00796 class __weak_count 00797 { 00798 public: 00799 constexpr __weak_count() noexcept : _M_pi(nullptr) 00800 { } 00801 00802 __weak_count(const __shared_count<_Lp>& __r) noexcept 00803 : _M_pi(__r._M_pi) 00804 { 00805 if (_M_pi != nullptr) 00806 _M_pi->_M_weak_add_ref(); 00807 } 00808 00809 __weak_count(const __weak_count& __r) noexcept 00810 : _M_pi(__r._M_pi) 00811 { 00812 if (_M_pi != nullptr) 00813 _M_pi->_M_weak_add_ref(); 00814 } 00815 00816 __weak_count(__weak_count&& __r) noexcept 00817 : _M_pi(__r._M_pi) 00818 { __r._M_pi = nullptr; } 00819 00820 ~__weak_count() noexcept 00821 { 00822 if (_M_pi != nullptr) 00823 _M_pi->_M_weak_release(); 00824 } 00825 00826 __weak_count& 00827 operator=(const __shared_count<_Lp>& __r) noexcept 00828 { 00829 _Sp_counted_base<_Lp>* __tmp = __r._M_pi; 00830 if (__tmp != nullptr) 00831 __tmp->_M_weak_add_ref(); 00832 if (_M_pi != nullptr) 00833 _M_pi->_M_weak_release(); 00834 _M_pi = __tmp; 00835 return *this; 00836 } 00837 00838 __weak_count& 00839 operator=(const __weak_count& __r) noexcept 00840 { 00841 _Sp_counted_base<_Lp>* __tmp = __r._M_pi; 00842 if (__tmp != nullptr) 00843 __tmp->_M_weak_add_ref(); 00844 if (_M_pi != nullptr) 00845 _M_pi->_M_weak_release(); 00846 _M_pi = __tmp; 00847 return *this; 00848 } 00849 00850 __weak_count& 00851 operator=(__weak_count&& __r) noexcept 00852 { 00853 if (_M_pi != nullptr) 00854 _M_pi->_M_weak_release(); 00855 _M_pi = __r._M_pi; 00856 __r._M_pi = nullptr; 00857 return *this; 00858 } 00859 00860 void 00861 _M_swap(__weak_count& __r) noexcept 00862 { 00863 _Sp_counted_base<_Lp>* __tmp = __r._M_pi; 00864 __r._M_pi = _M_pi; 00865 _M_pi = __tmp; 00866 } 00867 00868 long 00869 _M_get_use_count() const noexcept 00870 { return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; } 00871 00872 bool 00873 _M_less(const __weak_count& __rhs) const noexcept 00874 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } 00875 00876 bool 00877 _M_less(const __shared_count<_Lp>& __rhs) const noexcept 00878 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } 00879 00880 // Friend function injected into enclosing namespace and found by ADL 00881 friend inline bool 00882 operator==(const __weak_count& __a, const __weak_count& __b) noexcept 00883 { return __a._M_pi == __b._M_pi; } 00884 00885 private: 00886 friend class __shared_count<_Lp>; 00887 00888 _Sp_counted_base<_Lp>* _M_pi; 00889 }; 00890 00891 // Now that __weak_count is defined we can define this constructor: 00892 template<_Lock_policy _Lp> 00893 inline 00894 __shared_count<_Lp>::__shared_count(const __weak_count<_Lp>& __r) 00895 : _M_pi(__r._M_pi) 00896 { 00897 if (_M_pi != nullptr) 00898 _M_pi->_M_add_ref_lock(); 00899 else 00900 __throw_bad_weak_ptr(); 00901 } 00902 00903 // Now that __weak_count is defined we can define this constructor: 00904 template<_Lock_policy _Lp> 00905 inline 00906 __shared_count<_Lp>:: 00907 __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t) 00908 : _M_pi(__r._M_pi) 00909 { 00910 if (_M_pi != nullptr) 00911 if (!_M_pi->_M_add_ref_lock_nothrow()) 00912 _M_pi = nullptr; 00913 } 00914 00915 #define __cpp_lib_shared_ptr_arrays 201611L 00916 00917 // Helper traits for shared_ptr of array: 00918 00919 // A pointer type Y* is said to be compatible with a pointer type T* when 00920 // either Y* is convertible to T* or Y is U[N] and T is U cv []. 00921 template<typename _Yp_ptr, typename _Tp_ptr> 00922 struct __sp_compatible_with 00923 : false_type 00924 { }; 00925 00926 template<typename _Yp, typename _Tp> 00927 struct __sp_compatible_with<_Yp*, _Tp*> 00928 : is_convertible<_Yp*, _Tp*>::type 00929 { }; 00930 00931 template<typename _Up, size_t _Nm> 00932 struct __sp_compatible_with<_Up(*)[_Nm], _Up(*)[]> 00933 : true_type 00934 { }; 00935 00936 template<typename _Up, size_t _Nm> 00937 struct __sp_compatible_with<_Up(*)[_Nm], const _Up(*)[]> 00938 : true_type 00939 { }; 00940 00941 template<typename _Up, size_t _Nm> 00942 struct __sp_compatible_with<_Up(*)[_Nm], volatile _Up(*)[]> 00943 : true_type 00944 { }; 00945 00946 template<typename _Up, size_t _Nm> 00947 struct __sp_compatible_with<_Up(*)[_Nm], const volatile _Up(*)[]> 00948 : true_type 00949 { }; 00950 00951 // Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N]. 00952 template<typename _Up, size_t _Nm, typename _Yp, typename = void> 00953 struct __sp_is_constructible_arrN 00954 : false_type 00955 { }; 00956 00957 template<typename _Up, size_t _Nm, typename _Yp> 00958 struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>> 00959 : is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type 00960 { }; 00961 00962 // Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[]. 00963 template<typename _Up, typename _Yp, typename = void> 00964 struct __sp_is_constructible_arr 00965 : false_type 00966 { }; 00967 00968 template<typename _Up, typename _Yp> 00969 struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>> 00970 : is_convertible<_Yp(*)[], _Up(*)[]>::type 00971 { }; 00972 00973 // Trait to check if shared_ptr<T> can be constructed from Y*. 00974 template<typename _Tp, typename _Yp> 00975 struct __sp_is_constructible; 00976 00977 // When T is U[N], Y(*)[N] shall be convertible to T*; 00978 template<typename _Up, size_t _Nm, typename _Yp> 00979 struct __sp_is_constructible<_Up[_Nm], _Yp> 00980 : __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type 00981 { }; 00982 00983 // when T is U[], Y(*)[] shall be convertible to T*; 00984 template<typename _Up, typename _Yp> 00985 struct __sp_is_constructible<_Up[], _Yp> 00986 : __sp_is_constructible_arr<_Up, _Yp>::type 00987 { }; 00988 00989 // otherwise, Y* shall be convertible to T*. 00990 template<typename _Tp, typename _Yp> 00991 struct __sp_is_constructible 00992 : is_convertible<_Yp*, _Tp*>::type 00993 { }; 00994 00995 00996 // Define operator* and operator-> for shared_ptr<T>. 00997 template<typename _Tp, _Lock_policy _Lp, 00998 bool = is_array<_Tp>::value, bool = is_void<_Tp>::value> 00999 class __shared_ptr_access 01000 { 01001 public: 01002 using element_type = _Tp; 01003 01004 element_type& 01005 operator*() const noexcept 01006 { 01007 __glibcxx_assert(_M_get() != nullptr); 01008 return *_M_get(); 01009 } 01010 01011 element_type* 01012 operator->() const noexcept 01013 { 01014 _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr); 01015 return _M_get(); 01016 } 01017 01018 private: 01019 element_type* 01020 _M_get() const noexcept 01021 { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); } 01022 }; 01023 01024 // Define operator-> for shared_ptr<cv void>. 01025 template<typename _Tp, _Lock_policy _Lp> 01026 class __shared_ptr_access<_Tp, _Lp, false, true> 01027 { 01028 public: 01029 using element_type = _Tp; 01030 01031 element_type* 01032 operator->() const noexcept 01033 { 01034 auto __ptr = static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); 01035 _GLIBCXX_DEBUG_PEDASSERT(__ptr != nullptr); 01036 return __ptr; 01037 } 01038 }; 01039 01040 // Define operator[] for shared_ptr<T[]> and shared_ptr<T[N]>. 01041 template<typename _Tp, _Lock_policy _Lp> 01042 class __shared_ptr_access<_Tp, _Lp, true, false> 01043 { 01044 public: 01045 using element_type = typename remove_extent<_Tp>::type; 01046 01047 #if __cplusplus <= 201402L 01048 [[__deprecated__("shared_ptr<T[]>::operator* is absent from C++17")]] 01049 element_type& 01050 operator*() const noexcept 01051 { 01052 __glibcxx_assert(_M_get() != nullptr); 01053 return *_M_get(); 01054 } 01055 01056 [[__deprecated__("shared_ptr<T[]>::operator-> is absent from C++17")]] 01057 element_type* 01058 operator->() const noexcept 01059 { 01060 _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr); 01061 return _M_get(); 01062 } 01063 #endif 01064 01065 element_type& 01066 operator[](ptrdiff_t __i) const 01067 { 01068 __glibcxx_assert(_M_get() != nullptr); 01069 __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value); 01070 return _M_get()[__i]; 01071 } 01072 01073 private: 01074 element_type* 01075 _M_get() const noexcept 01076 { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); } 01077 }; 01078 01079 template<typename _Tp, _Lock_policy _Lp> 01080 class __shared_ptr 01081 : public __shared_ptr_access<_Tp, _Lp> 01082 { 01083 public: 01084 using element_type = typename remove_extent<_Tp>::type; 01085 01086 private: 01087 // Constraint for taking ownership of a pointer of type _Yp*: 01088 template<typename _Yp> 01089 using _SafeConv 01090 = typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type; 01091 01092 // Constraint for construction from shared_ptr and weak_ptr: 01093 template<typename _Yp, typename _Res = void> 01094 using _Compatible = typename 01095 enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type; 01096 01097 // Constraint for assignment from shared_ptr and weak_ptr: 01098 template<typename _Yp> 01099 using _Assignable = _Compatible<_Yp, __shared_ptr&>; 01100 01101 // Constraint for construction from unique_ptr: 01102 template<typename _Yp, typename _Del, typename _Res = void, 01103 typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer> 01104 using _UniqCompatible = typename enable_if<__and_< 01105 __sp_compatible_with<_Yp*, _Tp*>, is_convertible<_Ptr, element_type*> 01106 >::value, _Res>::type; 01107 01108 // Constraint for assignment from unique_ptr: 01109 template<typename _Yp, typename _Del> 01110 using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>; 01111 01112 public: 01113 01114 #if __cplusplus > 201402L 01115 using weak_type = __weak_ptr<_Tp, _Lp>; 01116 #endif 01117 01118 constexpr __shared_ptr() noexcept 01119 : _M_ptr(0), _M_refcount() 01120 { } 01121 01122 template<typename _Yp, typename = _SafeConv<_Yp>> 01123 explicit 01124 __shared_ptr(_Yp* __p) 01125 : _M_ptr(__p), _M_refcount(__p, typename is_array<_Tp>::type()) 01126 { 01127 static_assert( !is_void<_Yp>::value, "incomplete type" ); 01128 static_assert( sizeof(_Yp) > 0, "incomplete type" ); 01129 _M_enable_shared_from_this_with(__p); 01130 } 01131 01132 template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>> 01133 __shared_ptr(_Yp* __p, _Deleter __d) 01134 : _M_ptr(__p), _M_refcount(__p, std::move(__d)) 01135 { 01136 static_assert(__is_invocable<_Deleter&, _Yp*&>::value, 01137 "deleter expression d(p) is well-formed"); 01138 _M_enable_shared_from_this_with(__p); 01139 } 01140 01141 template<typename _Yp, typename _Deleter, typename _Alloc, 01142 typename = _SafeConv<_Yp>> 01143 __shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a) 01144 : _M_ptr(__p), _M_refcount(__p, std::move(__d), std::move(__a)) 01145 { 01146 static_assert(__is_invocable<_Deleter&, _Yp*&>::value, 01147 "deleter expression d(p) is well-formed"); 01148 _M_enable_shared_from_this_with(__p); 01149 } 01150 01151 template<typename _Deleter> 01152 __shared_ptr(nullptr_t __p, _Deleter __d) 01153 : _M_ptr(0), _M_refcount(__p, std::move(__d)) 01154 { } 01155 01156 template<typename _Deleter, typename _Alloc> 01157 __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a) 01158 : _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a)) 01159 { } 01160 01161 template<typename _Yp> 01162 __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r, 01163 element_type* __p) noexcept 01164 : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws 01165 { } 01166 01167 __shared_ptr(const __shared_ptr&) noexcept = default; 01168 __shared_ptr& operator=(const __shared_ptr&) noexcept = default; 01169 ~__shared_ptr() = default; 01170 01171 template<typename _Yp, typename = _Compatible<_Yp>> 01172 __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept 01173 : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) 01174 { } 01175 01176 __shared_ptr(__shared_ptr&& __r) noexcept 01177 : _M_ptr(__r._M_ptr), _M_refcount() 01178 { 01179 _M_refcount._M_swap(__r._M_refcount); 01180 __r._M_ptr = 0; 01181 } 01182 01183 template<typename _Yp, typename = _Compatible<_Yp>> 01184 __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept 01185 : _M_ptr(__r._M_ptr), _M_refcount() 01186 { 01187 _M_refcount._M_swap(__r._M_refcount); 01188 __r._M_ptr = 0; 01189 } 01190 01191 template<typename _Yp, typename = _Compatible<_Yp>> 01192 explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r) 01193 : _M_refcount(__r._M_refcount) // may throw 01194 { 01195 // It is now safe to copy __r._M_ptr, as 01196 // _M_refcount(__r._M_refcount) did not throw. 01197 _M_ptr = __r._M_ptr; 01198 } 01199 01200 // If an exception is thrown this constructor has no effect. 01201 template<typename _Yp, typename _Del, 01202 typename = _UniqCompatible<_Yp, _Del>> 01203 __shared_ptr(unique_ptr<_Yp, _Del>&& __r) 01204 : _M_ptr(__r.get()), _M_refcount() 01205 { 01206 auto __raw = __to_address(__r.get()); 01207 _M_refcount = __shared_count<_Lp>(std::move(__r)); 01208 _M_enable_shared_from_this_with(__raw); 01209 } 01210 01211 #if __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATED 01212 protected: 01213 // If an exception is thrown this constructor has no effect. 01214 template<typename _Tp1, typename _Del, 01215 typename enable_if<__and_< 01216 __not_<is_array<_Tp>>, is_array<_Tp1>, 01217 is_convertible<typename unique_ptr<_Tp1, _Del>::pointer, _Tp*> 01218 >::value, bool>::type = true> 01219 __shared_ptr(unique_ptr<_Tp1, _Del>&& __r, __sp_array_delete) 01220 : _M_ptr(__r.get()), _M_refcount() 01221 { 01222 auto __raw = __to_address(__r.get()); 01223 _M_refcount = __shared_count<_Lp>(std::move(__r)); 01224 _M_enable_shared_from_this_with(__raw); 01225 } 01226 public: 01227 #endif 01228 01229 #if _GLIBCXX_USE_DEPRECATED 01230 #pragma GCC diagnostic push 01231 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 01232 // Postcondition: use_count() == 1 and __r.get() == 0 01233 template<typename _Yp, typename = _Compatible<_Yp>> 01234 __shared_ptr(auto_ptr<_Yp>&& __r); 01235 #pragma GCC diagnostic pop 01236 #endif 01237 01238 constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { } 01239 01240 template<typename _Yp> 01241 _Assignable<_Yp> 01242 operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept 01243 { 01244 _M_ptr = __r._M_ptr; 01245 _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw 01246 return *this; 01247 } 01248 01249 #if _GLIBCXX_USE_DEPRECATED 01250 #pragma GCC diagnostic push 01251 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 01252 template<typename _Yp> 01253 _Assignable<_Yp> 01254 operator=(auto_ptr<_Yp>&& __r) 01255 { 01256 __shared_ptr(std::move(__r)).swap(*this); 01257 return *this; 01258 } 01259 #pragma GCC diagnostic pop 01260 #endif 01261 01262 __shared_ptr& 01263 operator=(__shared_ptr&& __r) noexcept 01264 { 01265 __shared_ptr(std::move(__r)).swap(*this); 01266 return *this; 01267 } 01268 01269 template<class _Yp> 01270 _Assignable<_Yp> 01271 operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept 01272 { 01273 __shared_ptr(std::move(__r)).swap(*this); 01274 return *this; 01275 } 01276 01277 template<typename _Yp, typename _Del> 01278 _UniqAssignable<_Yp, _Del> 01279 operator=(unique_ptr<_Yp, _Del>&& __r) 01280 { 01281 __shared_ptr(std::move(__r)).swap(*this); 01282 return *this; 01283 } 01284 01285 void 01286 reset() noexcept 01287 { __shared_ptr().swap(*this); } 01288 01289 template<typename _Yp> 01290 _SafeConv<_Yp> 01291 reset(_Yp* __p) // _Yp must be complete. 01292 { 01293 // Catch self-reset errors. 01294 __glibcxx_assert(__p == 0 || __p != _M_ptr); 01295 __shared_ptr(__p).swap(*this); 01296 } 01297 01298 template<typename _Yp, typename _Deleter> 01299 _SafeConv<_Yp> 01300 reset(_Yp* __p, _Deleter __d) 01301 { __shared_ptr(__p, std::move(__d)).swap(*this); } 01302 01303 template<typename _Yp, typename _Deleter, typename _Alloc> 01304 _SafeConv<_Yp> 01305 reset(_Yp* __p, _Deleter __d, _Alloc __a) 01306 { __shared_ptr(__p, std::move(__d), std::move(__a)).swap(*this); } 01307 01308 element_type* 01309 get() const noexcept 01310 { return _M_ptr; } 01311 01312 explicit operator bool() const // never throws 01313 { return _M_ptr == 0 ? false : true; } 01314 01315 bool 01316 unique() const noexcept 01317 { return _M_refcount._M_unique(); } 01318 01319 long 01320 use_count() const noexcept 01321 { return _M_refcount._M_get_use_count(); } 01322 01323 void 01324 swap(__shared_ptr<_Tp, _Lp>& __other) noexcept 01325 { 01326 std::swap(_M_ptr, __other._M_ptr); 01327 _M_refcount._M_swap(__other._M_refcount); 01328 } 01329 01330 template<typename _Tp1> 01331 bool 01332 owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept 01333 { return _M_refcount._M_less(__rhs._M_refcount); } 01334 01335 template<typename _Tp1> 01336 bool 01337 owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept 01338 { return _M_refcount._M_less(__rhs._M_refcount); } 01339 01340 protected: 01341 // This constructor is non-standard, it is used by allocate_shared. 01342 template<typename _Alloc, typename... _Args> 01343 __shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args) 01344 : _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...) 01345 { _M_enable_shared_from_this_with(_M_ptr); } 01346 01347 template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc, 01348 typename... _Args> 01349 friend __shared_ptr<_Tp1, _Lp1> 01350 __allocate_shared(const _Alloc& __a, _Args&&... __args); 01351 01352 // This constructor is used by __weak_ptr::lock() and 01353 // shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t). 01354 __shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t) 01355 : _M_refcount(__r._M_refcount, std::nothrow) 01356 { 01357 _M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr; 01358 } 01359 01360 friend class __weak_ptr<_Tp, _Lp>; 01361 01362 private: 01363 01364 template<typename _Yp> 01365 using __esft_base_t = decltype(__enable_shared_from_this_base( 01366 std::declval<const __shared_count<_Lp>&>(), 01367 std::declval<_Yp*>())); 01368 01369 // Detect an accessible and unambiguous enable_shared_from_this base. 01370 template<typename _Yp, typename = void> 01371 struct __has_esft_base 01372 : false_type { }; 01373 01374 template<typename _Yp> 01375 struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>> 01376 : __not_<is_array<_Tp>> { }; // No enable shared_from_this for arrays 01377 01378 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type> 01379 typename enable_if<__has_esft_base<_Yp2>::value>::type 01380 _M_enable_shared_from_this_with(_Yp* __p) noexcept 01381 { 01382 if (auto __base = __enable_shared_from_this_base(_M_refcount, __p)) 01383 __base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount); 01384 } 01385 01386 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type> 01387 typename enable_if<!__has_esft_base<_Yp2>::value>::type 01388 _M_enable_shared_from_this_with(_Yp*) noexcept 01389 { } 01390 01391 void* 01392 _M_get_deleter(const std::type_info& __ti) const noexcept 01393 { return _M_refcount._M_get_deleter(__ti); } 01394 01395 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr; 01396 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr; 01397 01398 template<typename _Del, typename _Tp1, _Lock_policy _Lp1> 01399 friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept; 01400 01401 template<typename _Del, typename _Tp1> 01402 friend _Del* get_deleter(const shared_ptr<_Tp1>&) noexcept; 01403 01404 element_type* _M_ptr; // Contained pointer. 01405 __shared_count<_Lp> _M_refcount; // Reference counter. 01406 }; 01407 01408 01409 // 20.7.2.2.7 shared_ptr comparisons 01410 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> 01411 inline bool 01412 operator==(const __shared_ptr<_Tp1, _Lp>& __a, 01413 const __shared_ptr<_Tp2, _Lp>& __b) noexcept 01414 { return __a.get() == __b.get(); } 01415 01416 template<typename _Tp, _Lock_policy _Lp> 01417 inline bool 01418 operator==(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept 01419 { return !__a; } 01420 01421 template<typename _Tp, _Lock_policy _Lp> 01422 inline bool 01423 operator==(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept 01424 { return !__a; } 01425 01426 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> 01427 inline bool 01428 operator!=(const __shared_ptr<_Tp1, _Lp>& __a, 01429 const __shared_ptr<_Tp2, _Lp>& __b) noexcept 01430 { return __a.get() != __b.get(); } 01431 01432 template<typename _Tp, _Lock_policy _Lp> 01433 inline bool 01434 operator!=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept 01435 { return (bool)__a; } 01436 01437 template<typename _Tp, _Lock_policy _Lp> 01438 inline bool 01439 operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept 01440 { return (bool)__a; } 01441 01442 template<typename _Tp, typename _Up, _Lock_policy _Lp> 01443 inline bool 01444 operator<(const __shared_ptr<_Tp, _Lp>& __a, 01445 const __shared_ptr<_Up, _Lp>& __b) noexcept 01446 { 01447 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type; 01448 using _Up_elt = typename __shared_ptr<_Up, _Lp>::element_type; 01449 using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type; 01450 return less<_Vp>()(__a.get(), __b.get()); 01451 } 01452 01453 template<typename _Tp, _Lock_policy _Lp> 01454 inline bool 01455 operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept 01456 { 01457 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type; 01458 return less<_Tp_elt*>()(__a.get(), nullptr); 01459 } 01460 01461 template<typename _Tp, _Lock_policy _Lp> 01462 inline bool 01463 operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept 01464 { 01465 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type; 01466 return less<_Tp_elt*>()(nullptr, __a.get()); 01467 } 01468 01469 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> 01470 inline bool 01471 operator<=(const __shared_ptr<_Tp1, _Lp>& __a, 01472 const __shared_ptr<_Tp2, _Lp>& __b) noexcept 01473 { return !(__b < __a); } 01474 01475 template<typename _Tp, _Lock_policy _Lp> 01476 inline bool 01477 operator<=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept 01478 { return !(nullptr < __a); } 01479 01480 template<typename _Tp, _Lock_policy _Lp> 01481 inline bool 01482 operator<=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept 01483 { return !(__a < nullptr); } 01484 01485 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> 01486 inline bool 01487 operator>(const __shared_ptr<_Tp1, _Lp>& __a, 01488 const __shared_ptr<_Tp2, _Lp>& __b) noexcept 01489 { return (__b < __a); } 01490 01491 template<typename _Tp, _Lock_policy _Lp> 01492 inline bool 01493 operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept 01494 { return nullptr < __a; } 01495 01496 template<typename _Tp, _Lock_policy _Lp> 01497 inline bool 01498 operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept 01499 { return __a < nullptr; } 01500 01501 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> 01502 inline bool 01503 operator>=(const __shared_ptr<_Tp1, _Lp>& __a, 01504 const __shared_ptr<_Tp2, _Lp>& __b) noexcept 01505 { return !(__a < __b); } 01506 01507 template<typename _Tp, _Lock_policy _Lp> 01508 inline bool 01509 operator>=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept 01510 { return !(__a < nullptr); } 01511 01512 template<typename _Tp, _Lock_policy _Lp> 01513 inline bool 01514 operator>=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept 01515 { return !(nullptr < __a); } 01516 01517 // 20.7.2.2.8 shared_ptr specialized algorithms. 01518 template<typename _Tp, _Lock_policy _Lp> 01519 inline void 01520 swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) noexcept 01521 { __a.swap(__b); } 01522 01523 // 20.7.2.2.9 shared_ptr casts 01524 01525 // The seemingly equivalent code: 01526 // shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get())) 01527 // will eventually result in undefined behaviour, attempting to 01528 // delete the same object twice. 01529 /// static_pointer_cast 01530 template<typename _Tp, typename _Tp1, _Lock_policy _Lp> 01531 inline __shared_ptr<_Tp, _Lp> 01532 static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept 01533 { 01534 using _Sp = __shared_ptr<_Tp, _Lp>; 01535 return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get())); 01536 } 01537 01538 // The seemingly equivalent code: 01539 // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get())) 01540 // will eventually result in undefined behaviour, attempting to 01541 // delete the same object twice. 01542 /// const_pointer_cast 01543 template<typename _Tp, typename _Tp1, _Lock_policy _Lp> 01544 inline __shared_ptr<_Tp, _Lp> 01545 const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept 01546 { 01547 using _Sp = __shared_ptr<_Tp, _Lp>; 01548 return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get())); 01549 } 01550 01551 // The seemingly equivalent code: 01552 // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get())) 01553 // will eventually result in undefined behaviour, attempting to 01554 // delete the same object twice. 01555 /// dynamic_pointer_cast 01556 template<typename _Tp, typename _Tp1, _Lock_policy _Lp> 01557 inline __shared_ptr<_Tp, _Lp> 01558 dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept 01559 { 01560 using _Sp = __shared_ptr<_Tp, _Lp>; 01561 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get())) 01562 return _Sp(__r, __p); 01563 return _Sp(); 01564 } 01565 01566 #if __cplusplus > 201402L 01567 template<typename _Tp, typename _Tp1, _Lock_policy _Lp> 01568 inline __shared_ptr<_Tp, _Lp> 01569 reinterpret_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept 01570 { 01571 using _Sp = __shared_ptr<_Tp, _Lp>; 01572 return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get())); 01573 } 01574 #endif 01575 01576 template<typename _Tp, _Lock_policy _Lp> 01577 class __weak_ptr 01578 { 01579 template<typename _Yp, typename _Res = void> 01580 using _Compatible = typename 01581 enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type; 01582 01583 // Constraint for assignment from shared_ptr and weak_ptr: 01584 template<typename _Yp> 01585 using _Assignable = _Compatible<_Yp, __weak_ptr&>; 01586 01587 public: 01588 using element_type = typename remove_extent<_Tp>::type; 01589 01590 constexpr __weak_ptr() noexcept 01591 : _M_ptr(nullptr), _M_refcount() 01592 { } 01593 01594 __weak_ptr(const __weak_ptr&) noexcept = default; 01595 01596 ~__weak_ptr() = default; 01597 01598 // The "obvious" converting constructor implementation: 01599 // 01600 // template<typename _Tp1> 01601 // __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) 01602 // : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws 01603 // { } 01604 // 01605 // has a serious problem. 01606 // 01607 // __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr) 01608 // conversion may require access to *__r._M_ptr (virtual inheritance). 01609 // 01610 // It is not possible to avoid spurious access violations since 01611 // in multithreaded programs __r._M_ptr may be invalidated at any point. 01612 template<typename _Yp, typename = _Compatible<_Yp>> 01613 __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept 01614 : _M_refcount(__r._M_refcount) 01615 { _M_ptr = __r.lock().get(); } 01616 01617 template<typename _Yp, typename = _Compatible<_Yp>> 01618 __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept 01619 : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) 01620 { } 01621 01622 __weak_ptr(__weak_ptr&& __r) noexcept 01623 : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount)) 01624 { __r._M_ptr = nullptr; } 01625 01626 template<typename _Yp, typename = _Compatible<_Yp>> 01627 __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept 01628 : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount)) 01629 { __r._M_ptr = nullptr; } 01630 01631 __weak_ptr& 01632 operator=(const __weak_ptr& __r) noexcept = default; 01633 01634 template<typename _Yp> 01635 _Assignable<_Yp> 01636 operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept 01637 { 01638 _M_ptr = __r.lock().get(); 01639 _M_refcount = __r._M_refcount; 01640 return *this; 01641 } 01642 01643 template<typename _Yp> 01644 _Assignable<_Yp> 01645 operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept 01646 { 01647 _M_ptr = __r._M_ptr; 01648 _M_refcount = __r._M_refcount; 01649 return *this; 01650 } 01651 01652 __weak_ptr& 01653 operator=(__weak_ptr&& __r) noexcept 01654 { 01655 _M_ptr = __r._M_ptr; 01656 _M_refcount = std::move(__r._M_refcount); 01657 __r._M_ptr = nullptr; 01658 return *this; 01659 } 01660 01661 template<typename _Yp> 01662 _Assignable<_Yp> 01663 operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept 01664 { 01665 _M_ptr = __r.lock().get(); 01666 _M_refcount = std::move(__r._M_refcount); 01667 __r._M_ptr = nullptr; 01668 return *this; 01669 } 01670 01671 __shared_ptr<_Tp, _Lp> 01672 lock() const noexcept 01673 { return __shared_ptr<element_type, _Lp>(*this, std::nothrow); } 01674 01675 long 01676 use_count() const noexcept 01677 { return _M_refcount._M_get_use_count(); } 01678 01679 bool 01680 expired() const noexcept 01681 { return _M_refcount._M_get_use_count() == 0; } 01682 01683 template<typename _Tp1> 01684 bool 01685 owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const noexcept 01686 { return _M_refcount._M_less(__rhs._M_refcount); } 01687 01688 template<typename _Tp1> 01689 bool 01690 owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept 01691 { return _M_refcount._M_less(__rhs._M_refcount); } 01692 01693 void 01694 reset() noexcept 01695 { __weak_ptr().swap(*this); } 01696 01697 void 01698 swap(__weak_ptr& __s) noexcept 01699 { 01700 std::swap(_M_ptr, __s._M_ptr); 01701 _M_refcount._M_swap(__s._M_refcount); 01702 } 01703 01704 private: 01705 // Used by __enable_shared_from_this. 01706 void 01707 _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) noexcept 01708 { 01709 if (use_count() == 0) 01710 { 01711 _M_ptr = __ptr; 01712 _M_refcount = __refcount; 01713 } 01714 } 01715 01716 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr; 01717 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr; 01718 friend class __enable_shared_from_this<_Tp, _Lp>; 01719 friend class enable_shared_from_this<_Tp>; 01720 01721 element_type* _M_ptr; // Contained pointer. 01722 __weak_count<_Lp> _M_refcount; // Reference counter. 01723 }; 01724 01725 // 20.7.2.3.6 weak_ptr specialized algorithms. 01726 template<typename _Tp, _Lock_policy _Lp> 01727 inline void 01728 swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) noexcept 01729 { __a.swap(__b); } 01730 01731 template<typename _Tp, typename _Tp1> 01732 struct _Sp_owner_less : public binary_function<_Tp, _Tp, bool> 01733 { 01734 bool 01735 operator()(const _Tp& __lhs, const _Tp& __rhs) const noexcept 01736 { return __lhs.owner_before(__rhs); } 01737 01738 bool 01739 operator()(const _Tp& __lhs, const _Tp1& __rhs) const noexcept 01740 { return __lhs.owner_before(__rhs); } 01741 01742 bool 01743 operator()(const _Tp1& __lhs, const _Tp& __rhs) const noexcept 01744 { return __lhs.owner_before(__rhs); } 01745 }; 01746 01747 template<> 01748 struct _Sp_owner_less<void, void> 01749 { 01750 template<typename _Tp, typename _Up> 01751 auto 01752 operator()(const _Tp& __lhs, const _Up& __rhs) const noexcept 01753 -> decltype(__lhs.owner_before(__rhs)) 01754 { return __lhs.owner_before(__rhs); } 01755 01756 using is_transparent = void; 01757 }; 01758 01759 template<typename _Tp, _Lock_policy _Lp> 01760 struct owner_less<__shared_ptr<_Tp, _Lp>> 01761 : public _Sp_owner_less<__shared_ptr<_Tp, _Lp>, __weak_ptr<_Tp, _Lp>> 01762 { }; 01763 01764 template<typename _Tp, _Lock_policy _Lp> 01765 struct owner_less<__weak_ptr<_Tp, _Lp>> 01766 : public _Sp_owner_less<__weak_ptr<_Tp, _Lp>, __shared_ptr<_Tp, _Lp>> 01767 { }; 01768 01769 01770 template<typename _Tp, _Lock_policy _Lp> 01771 class __enable_shared_from_this 01772 { 01773 protected: 01774 constexpr __enable_shared_from_this() noexcept { } 01775 01776 __enable_shared_from_this(const __enable_shared_from_this&) noexcept { } 01777 01778 __enable_shared_from_this& 01779 operator=(const __enable_shared_from_this&) noexcept 01780 { return *this; } 01781 01782 ~__enable_shared_from_this() { } 01783 01784 public: 01785 __shared_ptr<_Tp, _Lp> 01786 shared_from_this() 01787 { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); } 01788 01789 __shared_ptr<const _Tp, _Lp> 01790 shared_from_this() const 01791 { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); } 01792 01793 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 01794 __weak_ptr<_Tp, _Lp> 01795 weak_from_this() noexcept 01796 { return this->_M_weak_this; } 01797 01798 __weak_ptr<const _Tp, _Lp> 01799 weak_from_this() const noexcept 01800 { return this->_M_weak_this; } 01801 #endif 01802 01803 private: 01804 template<typename _Tp1> 01805 void 01806 _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const noexcept 01807 { _M_weak_this._M_assign(__p, __n); } 01808 01809 friend const __enable_shared_from_this* 01810 __enable_shared_from_this_base(const __shared_count<_Lp>&, 01811 const __enable_shared_from_this* __p) 01812 { return __p; } 01813 01814 template<typename, _Lock_policy> 01815 friend class __shared_ptr; 01816 01817 mutable __weak_ptr<_Tp, _Lp> _M_weak_this; 01818 }; 01819 01820 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy, 01821 typename _Alloc, typename... _Args> 01822 inline __shared_ptr<_Tp, _Lp> 01823 __allocate_shared(const _Alloc& __a, _Args&&... __args) 01824 { 01825 return __shared_ptr<_Tp, _Lp>(_Sp_alloc_shared_tag<_Alloc>{__a}, 01826 std::forward<_Args>(__args)...); 01827 } 01828 01829 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy, 01830 typename... _Args> 01831 inline __shared_ptr<_Tp, _Lp> 01832 __make_shared(_Args&&... __args) 01833 { 01834 typedef typename std::remove_const<_Tp>::type _Tp_nc; 01835 return std::__allocate_shared<_Tp, _Lp>(std::allocator<_Tp_nc>(), 01836 std::forward<_Args>(__args)...); 01837 } 01838 01839 /// std::hash specialization for __shared_ptr. 01840 template<typename _Tp, _Lock_policy _Lp> 01841 struct hash<__shared_ptr<_Tp, _Lp>> 01842 : public __hash_base<size_t, __shared_ptr<_Tp, _Lp>> 01843 { 01844 size_t 01845 operator()(const __shared_ptr<_Tp, _Lp>& __s) const noexcept 01846 { 01847 return hash<typename __shared_ptr<_Tp, _Lp>::element_type*>()( 01848 __s.get()); 01849 } 01850 }; 01851 01852 _GLIBCXX_END_NAMESPACE_VERSION 01853 } // namespace 01854 01855 #endif // _SHARED_PTR_BASE_H