source: Daodan/MSYS2/mingw32/include/c++/11.2.0/bits/shared_ptr_base.h@ 1181

Last change on this file since 1181 was 1166, checked in by rossy, 3 years ago

Daodan: Replace MinGW build env with an up-to-date MSYS2 env

File size: 53.7 KB
Line 
1// shared_ptr and weak_ptr implementation details -*- C++ -*-
2
3// Copyright (C) 2007-2021 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25// GCC Note: Based on files from version 1.32.0 of the Boost library.
26
27// shared_count.hpp
28// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29
30// shared_ptr.hpp
31// Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32// Copyright (C) 2001, 2002, 2003 Peter Dimov
33
34// weak_ptr.hpp
35// Copyright (C) 2001, 2002, 2003 Peter Dimov
36
37// enable_shared_from_this.hpp
38// Copyright (C) 2002 Peter Dimov
39
40// Distributed under the Boost Software License, Version 1.0. (See
41// accompanying file LICENSE_1_0.txt or copy at
42// http://www.boost.org/LICENSE_1_0.txt)
43
44/** @file bits/shared_ptr_base.h
45 * This is an internal header file, included by other library headers.
46 * Do not attempt to use it directly. @headername{memory}
47 */
48
49#ifndef _SHARED_PTR_BASE_H
50#define _SHARED_PTR_BASE_H 1
51
52#include <typeinfo>
53#include <bits/allocated_ptr.h>
54#include <bits/allocator.h>
55#include <bits/exception_defines.h>
56#include <bits/functional_hash.h>
57#include <bits/refwrap.h>
58#include <bits/stl_function.h> // std::less
59#include <bits/unique_ptr.h>
60#include <ext/aligned_buffer.h>
61#include <ext/atomicity.h>
62#include <ext/concurrence.h>
63#if __cplusplus > 201703L
64# include <compare>
65#endif
66
67namespace std _GLIBCXX_VISIBILITY(default)
68{
69_GLIBCXX_BEGIN_NAMESPACE_VERSION
70
71#if _GLIBCXX_USE_DEPRECATED
72#pragma GCC diagnostic push
73#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
74 template<typename> class auto_ptr;
75#pragma GCC diagnostic pop
76#endif
77
78 /**
79 * @brief Exception possibly thrown by @c shared_ptr.
80 * @ingroup exceptions
81 */
82 class bad_weak_ptr : public std::exception
83 {
84 public:
85 virtual char const* what() const noexcept;
86
87 virtual ~bad_weak_ptr() noexcept;
88 };
89
90 // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
91 inline void
92 __throw_bad_weak_ptr()
93 { _GLIBCXX_THROW_OR_ABORT(bad_weak_ptr()); }
94
95 using __gnu_cxx::_Lock_policy;
96 using __gnu_cxx::__default_lock_policy;
97 using __gnu_cxx::_S_single;
98 using __gnu_cxx::_S_mutex;
99 using __gnu_cxx::_S_atomic;
100
101 // Empty helper class except when the template argument is _S_mutex.
102 template<_Lock_policy _Lp>
103 class _Mutex_base
104 {
105 protected:
106 // The atomic policy uses fully-fenced builtins, single doesn't care.
107 enum { _S_need_barriers = 0 };
108 };
109
110 template<>
111 class _Mutex_base<_S_mutex>
112 : public __gnu_cxx::__mutex
113 {
114 protected:
115 // This policy is used when atomic builtins are not available.
116 // The replacement atomic operations might not have the necessary
117 // memory barriers.
118 enum { _S_need_barriers = 1 };
119 };
120
121 template<_Lock_policy _Lp = __default_lock_policy>
122 class _Sp_counted_base
123 : public _Mutex_base<_Lp>
124 {
125 public:
126 _Sp_counted_base() noexcept
127 : _M_use_count(1), _M_weak_count(1) { }
128
129 virtual
130 ~_Sp_counted_base() noexcept
131 { }
132
133 // Called when _M_use_count drops to zero, to release the resources
134 // managed by *this.
135 virtual void
136 _M_dispose() noexcept = 0;
137
138 // Called when _M_weak_count drops to zero.
139 virtual void
140 _M_destroy() noexcept
141 { delete this; }
142
143 virtual void*
144 _M_get_deleter(const std::type_info&) noexcept = 0;
145
146 void
147 _M_add_ref_copy()
148 { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
149
150 void
151 _M_add_ref_lock()
152 {
153 if (!_M_add_ref_lock_nothrow())
154 __throw_bad_weak_ptr();
155 }
156
157 bool
158 _M_add_ref_lock_nothrow() noexcept;
159
160 void
161 _M_release() noexcept
162 {
163 // Be race-detector-friendly. For more info see bits/c++config.
164 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
165 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
166 {
167 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
168 _M_dispose();
169 // There must be a memory barrier between dispose() and destroy()
170 // to ensure that the effects of dispose() are observed in the
171 // thread that runs destroy().
172 // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
173 if (_Mutex_base<_Lp>::_S_need_barriers)
174 {
175 __atomic_thread_fence (__ATOMIC_ACQ_REL);
176 }
177
178 // Be race-detector-friendly. For more info see bits/c++config.
179 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
180 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
181 -1) == 1)
182 {
183 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
184 _M_destroy();
185 }
186 }
187 }
188
189 void
190 _M_weak_add_ref() noexcept
191 { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
192
193 void
194 _M_weak_release() noexcept
195 {
196 // Be race-detector-friendly. For more info see bits/c++config.
197 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
198 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
199 {
200 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
201 if (_Mutex_base<_Lp>::_S_need_barriers)
202 {
203 // See _M_release(),
204 // destroy() must observe results of dispose()
205 __atomic_thread_fence (__ATOMIC_ACQ_REL);
206 }
207 _M_destroy();
208 }
209 }
210
211 long
212 _M_get_use_count() const noexcept
213 {
214 // No memory barrier is used here so there is no synchronization
215 // with other threads.
216 return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED);
217 }
218
219 private:
220 _Sp_counted_base(_Sp_counted_base const&) = delete;
221 _Sp_counted_base& operator=(_Sp_counted_base const&) = delete;
222
223 _Atomic_word _M_use_count; // #shared
224 _Atomic_word _M_weak_count; // #weak + (#shared != 0)
225 };
226
227 template<>
228 inline bool
229 _Sp_counted_base<_S_single>::
230 _M_add_ref_lock_nothrow() noexcept
231 {
232 if (_M_use_count == 0)
233 return false;
234 ++_M_use_count;
235 return true;
236 }
237
238 template<>
239 inline bool
240 _Sp_counted_base<_S_mutex>::
241 _M_add_ref_lock_nothrow() noexcept
242 {
243 __gnu_cxx::__scoped_lock sentry(*this);
244 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
245 {
246 _M_use_count = 0;
247 return false;
248 }
249 return true;
250 }
251
252 template<>
253 inline bool
254 _Sp_counted_base<_S_atomic>::
255 _M_add_ref_lock_nothrow() noexcept
256 {
257 // Perform lock-free add-if-not-zero operation.
258 _Atomic_word __count = _M_get_use_count();
259 do
260 {
261 if (__count == 0)
262 return false;
263 // Replace the current counter value with the old value + 1, as
264 // long as it's not changed meanwhile.
265 }
266 while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
267 true, __ATOMIC_ACQ_REL,
268 __ATOMIC_RELAXED));
269 return true;
270 }
271
272 template<>
273 inline void
274 _Sp_counted_base<_S_single>::_M_add_ref_copy()
275 { ++_M_use_count; }
276
277 template<>
278 inline void
279 _Sp_counted_base<_S_single>::_M_release() noexcept
280 {
281 if (--_M_use_count == 0)
282 {
283 _M_dispose();
284 if (--_M_weak_count == 0)
285 _M_destroy();
286 }
287 }
288
289 template<>
290 inline void
291 _Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept
292 { ++_M_weak_count; }
293
294 template<>
295 inline void
296 _Sp_counted_base<_S_single>::_M_weak_release() noexcept
297 {
298 if (--_M_weak_count == 0)
299 _M_destroy();
300 }
301
302 template<>
303 inline long
304 _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept
305 { return _M_use_count; }
306
307
308 // Forward declarations.
309 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
310 class __shared_ptr;
311
312 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
313 class __weak_ptr;
314
315 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
316 class __enable_shared_from_this;
317
318 template<typename _Tp>
319 class shared_ptr;
320
321 template<typename _Tp>
322 class weak_ptr;
323
324 template<typename _Tp>
325 struct owner_less;
326
327 template<typename _Tp>
328 class enable_shared_from_this;
329
330 template<_Lock_policy _Lp = __default_lock_policy>
331 class __weak_count;
332
333 template<_Lock_policy _Lp = __default_lock_policy>
334 class __shared_count;
335
336
337 // Counted ptr with no deleter or allocator support
338 template<typename _Ptr, _Lock_policy _Lp>
339 class _Sp_counted_ptr final : public _Sp_counted_base<_Lp>
340 {
341 public:
342 explicit
343 _Sp_counted_ptr(_Ptr __p) noexcept
344 : _M_ptr(__p) { }
345
346 virtual void
347 _M_dispose() noexcept
348 { delete _M_ptr; }
349
350 virtual void
351 _M_destroy() noexcept
352 { delete this; }
353
354 virtual void*
355 _M_get_deleter(const std::type_info&) noexcept
356 { return nullptr; }
357
358 _Sp_counted_ptr(const _Sp_counted_ptr&) = delete;
359 _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete;
360
361 private:
362 _Ptr _M_ptr;
363 };
364
365 template<>
366 inline void
367 _Sp_counted_ptr<nullptr_t, _S_single>::_M_dispose() noexcept { }
368
369 template<>
370 inline void
371 _Sp_counted_ptr<nullptr_t, _S_mutex>::_M_dispose() noexcept { }
372
373 template<>
374 inline void
375 _Sp_counted_ptr<nullptr_t, _S_atomic>::_M_dispose() noexcept { }
376
377 template<int _Nm, typename _Tp,
378 bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)>
379 struct _Sp_ebo_helper;
380
381 /// Specialization using EBO.
382 template<int _Nm, typename _Tp>
383 struct _Sp_ebo_helper<_Nm, _Tp, true> : private _Tp
384 {
385 explicit _Sp_ebo_helper(const _Tp& __tp) : _Tp(__tp) { }
386 explicit _Sp_ebo_helper(_Tp&& __tp) : _Tp(std::move(__tp)) { }
387
388 static _Tp&
389 _S_get(_Sp_ebo_helper& __eboh) { return static_cast<_Tp&>(__eboh); }
390 };
391
392 /// Specialization not using EBO.
393 template<int _Nm, typename _Tp>
394 struct _Sp_ebo_helper<_Nm, _Tp, false>
395 {
396 explicit _Sp_ebo_helper(const _Tp& __tp) : _M_tp(__tp) { }
397 explicit _Sp_ebo_helper(_Tp&& __tp) : _M_tp(std::move(__tp)) { }
398
399 static _Tp&
400 _S_get(_Sp_ebo_helper& __eboh)
401 { return __eboh._M_tp; }
402
403 private:
404 _Tp _M_tp;
405 };
406
407 // Support for custom deleter and/or allocator
408 template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp>
409 class _Sp_counted_deleter final : public _Sp_counted_base<_Lp>
410 {
411 class _Impl : _Sp_ebo_helper<0, _Deleter>, _Sp_ebo_helper<1, _Alloc>
412 {
413 typedef _Sp_ebo_helper<0, _Deleter> _Del_base;
414 typedef _Sp_ebo_helper<1, _Alloc> _Alloc_base;
415
416 public:
417 _Impl(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
418 : _Del_base(std::move(__d)), _Alloc_base(__a), _M_ptr(__p)
419 { }
420
421 _Deleter& _M_del() noexcept { return _Del_base::_S_get(*this); }
422 _Alloc& _M_alloc() noexcept { return _Alloc_base::_S_get(*this); }
423
424 _Ptr _M_ptr;
425 };
426
427 public:
428 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_deleter>;
429
430 // __d(__p) must not throw.
431 _Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept
432 : _M_impl(__p, std::move(__d), _Alloc()) { }
433
434 // __d(__p) must not throw.
435 _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) noexcept
436 : _M_impl(__p, std::move(__d), __a) { }
437
438 ~_Sp_counted_deleter() noexcept { }
439
440 virtual void
441 _M_dispose() noexcept
442 { _M_impl._M_del()(_M_impl._M_ptr); }
443
444 virtual void
445 _M_destroy() noexcept
446 {
447 __allocator_type __a(_M_impl._M_alloc());
448 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
449 this->~_Sp_counted_deleter();
450 }
451
452 virtual void*
453 _M_get_deleter(const type_info& __ti [[__gnu__::__unused__]]) noexcept
454 {
455#if __cpp_rtti
456 // _GLIBCXX_RESOLVE_LIB_DEFECTS
457 // 2400. shared_ptr's get_deleter() should use addressof()
458 return __ti == typeid(_Deleter)
459 ? std::__addressof(_M_impl._M_del())
460 : nullptr;
461#else
462 return nullptr;
463#endif
464 }
465
466 private:
467 _Impl _M_impl;
468 };
469
470 // helpers for make_shared / allocate_shared
471
472 struct _Sp_make_shared_tag
473 {
474 private:
475 template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
476 friend class _Sp_counted_ptr_inplace;
477
478 static const type_info&
479 _S_ti() noexcept _GLIBCXX_VISIBILITY(default)
480 {
481 alignas(type_info) static constexpr char __tag[sizeof(type_info)] = { };
482 return reinterpret_cast<const type_info&>(__tag);
483 }
484
485 static bool _S_eq(const type_info&) noexcept;
486 };
487
488 template<typename _Alloc>
489 struct _Sp_alloc_shared_tag
490 {
491 const _Alloc& _M_a;
492 };
493
494 template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
495 class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp>
496 {
497 class _Impl : _Sp_ebo_helper<0, _Alloc>
498 {
499 typedef _Sp_ebo_helper<0, _Alloc> _A_base;
500
501 public:
502 explicit _Impl(_Alloc __a) noexcept : _A_base(__a) { }
503
504 _Alloc& _M_alloc() noexcept { return _A_base::_S_get(*this); }
505
506 __gnu_cxx::__aligned_buffer<_Tp> _M_storage;
507 };
508
509 public:
510 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>;
511
512 // Alloc parameter is not a reference so doesn't alias anything in __args
513 template<typename... _Args>
514 _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args)
515 : _M_impl(__a)
516 {
517 // _GLIBCXX_RESOLVE_LIB_DEFECTS
518 // 2070. allocate_shared should use allocator_traits<A>::construct
519 allocator_traits<_Alloc>::construct(__a, _M_ptr(),
520 std::forward<_Args>(__args)...); // might throw
521 }
522
523 ~_Sp_counted_ptr_inplace() noexcept { }
524
525 virtual void
526 _M_dispose() noexcept
527 {
528 allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr());
529 }
530
531 // Override because the allocator needs to know the dynamic type
532 virtual void
533 _M_destroy() noexcept
534 {
535 __allocator_type __a(_M_impl._M_alloc());
536 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
537 this->~_Sp_counted_ptr_inplace();
538 }
539
540 private:
541 friend class __shared_count<_Lp>; // To be able to call _M_ptr().
542
543 // No longer used, but code compiled against old libstdc++ headers
544 // might still call it from __shared_ptr ctor to get the pointer out.
545 virtual void*
546 _M_get_deleter(const std::type_info& __ti) noexcept override
547 {
548 auto __ptr = const_cast<typename remove_cv<_Tp>::type*>(_M_ptr());
549 // Check for the fake type_info first, so we don't try to access it
550 // as a real type_info object. Otherwise, check if it's the real
551 // type_info for this class. With RTTI enabled we can check directly,
552 // or call a library function to do it.
553 if (&__ti == &_Sp_make_shared_tag::_S_ti()
554 ||
555#if __cpp_rtti
556 __ti == typeid(_Sp_make_shared_tag)
557#else
558 _Sp_make_shared_tag::_S_eq(__ti)
559#endif
560 )
561 return __ptr;
562 return nullptr;
563 }
564
565 _Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); }
566
567 _Impl _M_impl;
568 };
569
570 // The default deleter for shared_ptr<T[]> and shared_ptr<T[N]>.
571 struct __sp_array_delete
572 {
573 template<typename _Yp>
574 void operator()(_Yp* __p) const { delete[] __p; }
575 };
576
577 template<_Lock_policy _Lp>
578 class __shared_count
579 {
580 template<typename _Tp>
581 struct __not_alloc_shared_tag { using type = void; };
582
583 template<typename _Tp>
584 struct __not_alloc_shared_tag<_Sp_alloc_shared_tag<_Tp>> { };
585
586 public:
587 constexpr __shared_count() noexcept : _M_pi(0)
588 { }
589
590 template<typename _Ptr>
591 explicit
592 __shared_count(_Ptr __p) : _M_pi(0)
593 {
594 __try
595 {
596 _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);
597 }
598 __catch(...)
599 {
600 delete __p;
601 __throw_exception_again;
602 }
603 }
604
605 template<typename _Ptr>
606 __shared_count(_Ptr __p, /* is_array = */ false_type)
607 : __shared_count(__p)
608 { }
609
610 template<typename _Ptr>
611 __shared_count(_Ptr __p, /* is_array = */ true_type)
612 : __shared_count(__p, __sp_array_delete{}, allocator<void>())
613 { }
614
615 template<typename _Ptr, typename _Deleter,
616 typename = typename __not_alloc_shared_tag<_Deleter>::type>
617 __shared_count(_Ptr __p, _Deleter __d)
618 : __shared_count(__p, std::move(__d), allocator<void>())
619 { }
620
621 template<typename _Ptr, typename _Deleter, typename _Alloc,
622 typename = typename __not_alloc_shared_tag<_Deleter>::type>
623 __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
624 {
625 typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
626 __try
627 {
628 typename _Sp_cd_type::__allocator_type __a2(__a);
629 auto __guard = std::__allocate_guarded(__a2);
630 _Sp_cd_type* __mem = __guard.get();
631 ::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a));
632 _M_pi = __mem;
633 __guard = nullptr;
634 }
635 __catch(...)
636 {
637 __d(__p); // Call _Deleter on __p.
638 __throw_exception_again;
639 }
640 }
641
642 template<typename _Tp, typename _Alloc, typename... _Args>
643 __shared_count(_Tp*& __p, _Sp_alloc_shared_tag<_Alloc> __a,
644 _Args&&... __args)
645 {
646 typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;
647 typename _Sp_cp_type::__allocator_type __a2(__a._M_a);
648 auto __guard = std::__allocate_guarded(__a2);
649 _Sp_cp_type* __mem = __guard.get();
650 auto __pi = ::new (__mem)
651 _Sp_cp_type(__a._M_a, std::forward<_Args>(__args)...);
652 __guard = nullptr;
653 _M_pi = __pi;
654 __p = __pi->_M_ptr();
655 }
656
657#if _GLIBCXX_USE_DEPRECATED
658#pragma GCC diagnostic push
659#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
660 // Special case for auto_ptr<_Tp> to provide the strong guarantee.
661 template<typename _Tp>
662 explicit
663 __shared_count(std::auto_ptr<_Tp>&& __r);
664#pragma GCC diagnostic pop
665#endif
666
667 // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee.
668 template<typename _Tp, typename _Del>
669 explicit
670 __shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0)
671 {
672 // _GLIBCXX_RESOLVE_LIB_DEFECTS
673 // 2415. Inconsistency between unique_ptr and shared_ptr
674 if (__r.get() == nullptr)
675 return;
676
677 using _Ptr = typename unique_ptr<_Tp, _Del>::pointer;
678 using _Del2 = typename conditional<is_reference<_Del>::value,
679 reference_wrapper<typename remove_reference<_Del>::type>,
680 _Del>::type;
681 using _Sp_cd_type
682 = _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>;
683 using _Alloc = allocator<_Sp_cd_type>;
684 using _Alloc_traits = allocator_traits<_Alloc>;
685 _Alloc __a;
686 _Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1);
687 // _GLIBCXX_RESOLVE_LIB_DEFECTS
688 // 3548. shared_ptr construction from unique_ptr should move
689 // (not copy) the deleter
690 _Alloc_traits::construct(__a, __mem, __r.release(),
691 std::forward<_Del>(__r.get_deleter()));
692 _M_pi = __mem;
693 }
694
695 // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
696 explicit __shared_count(const __weak_count<_Lp>& __r);
697
698 // Does not throw if __r._M_get_use_count() == 0, caller must check.
699 explicit
700 __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t) noexcept;
701
702 ~__shared_count() noexcept
703 {
704 if (_M_pi != nullptr)
705 _M_pi->_M_release();
706 }
707
708 __shared_count(const __shared_count& __r) noexcept
709 : _M_pi(__r._M_pi)
710 {
711 if (_M_pi != nullptr)
712 _M_pi->_M_add_ref_copy();
713 }
714
715 __shared_count&
716 operator=(const __shared_count& __r) noexcept
717 {
718 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
719 if (__tmp != _M_pi)
720 {
721 if (__tmp != nullptr)
722 __tmp->_M_add_ref_copy();
723 if (_M_pi != nullptr)
724 _M_pi->_M_release();
725 _M_pi = __tmp;
726 }
727 return *this;
728 }
729
730 void
731 _M_swap(__shared_count& __r) noexcept
732 {
733 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
734 __r._M_pi = _M_pi;
735 _M_pi = __tmp;
736 }
737
738 long
739 _M_get_use_count() const noexcept
740 { return _M_pi ? _M_pi->_M_get_use_count() : 0; }
741
742 bool
743 _M_unique() const noexcept
744 { return this->_M_get_use_count() == 1; }
745
746 void*
747 _M_get_deleter(const std::type_info& __ti) const noexcept
748 { return _M_pi ? _M_pi->_M_get_deleter(__ti) : nullptr; }
749
750 bool
751 _M_less(const __shared_count& __rhs) const noexcept
752 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
753
754 bool
755 _M_less(const __weak_count<_Lp>& __rhs) const noexcept
756 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
757
758 // Friend function injected into enclosing namespace and found by ADL
759 friend inline bool
760 operator==(const __shared_count& __a, const __shared_count& __b) noexcept
761 { return __a._M_pi == __b._M_pi; }
762
763 private:
764 friend class __weak_count<_Lp>;
765
766 _Sp_counted_base<_Lp>* _M_pi;
767 };
768
769
770 template<_Lock_policy _Lp>
771 class __weak_count
772 {
773 public:
774 constexpr __weak_count() noexcept : _M_pi(nullptr)
775 { }
776
777 __weak_count(const __shared_count<_Lp>& __r) noexcept
778 : _M_pi(__r._M_pi)
779 {
780 if (_M_pi != nullptr)
781 _M_pi->_M_weak_add_ref();
782 }
783
784 __weak_count(const __weak_count& __r) noexcept
785 : _M_pi(__r._M_pi)
786 {
787 if (_M_pi != nullptr)
788 _M_pi->_M_weak_add_ref();
789 }
790
791 __weak_count(__weak_count&& __r) noexcept
792 : _M_pi(__r._M_pi)
793 { __r._M_pi = nullptr; }
794
795 ~__weak_count() noexcept
796 {
797 if (_M_pi != nullptr)
798 _M_pi->_M_weak_release();
799 }
800
801 __weak_count&
802 operator=(const __shared_count<_Lp>& __r) noexcept
803 {
804 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
805 if (__tmp != nullptr)
806 __tmp->_M_weak_add_ref();
807 if (_M_pi != nullptr)
808 _M_pi->_M_weak_release();
809 _M_pi = __tmp;
810 return *this;
811 }
812
813 __weak_count&
814 operator=(const __weak_count& __r) noexcept
815 {
816 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
817 if (__tmp != nullptr)
818 __tmp->_M_weak_add_ref();
819 if (_M_pi != nullptr)
820 _M_pi->_M_weak_release();
821 _M_pi = __tmp;
822 return *this;
823 }
824
825 __weak_count&
826 operator=(__weak_count&& __r) noexcept
827 {
828 if (_M_pi != nullptr)
829 _M_pi->_M_weak_release();
830 _M_pi = __r._M_pi;
831 __r._M_pi = nullptr;
832 return *this;
833 }
834
835 void
836 _M_swap(__weak_count& __r) noexcept
837 {
838 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
839 __r._M_pi = _M_pi;
840 _M_pi = __tmp;
841 }
842
843 long
844 _M_get_use_count() const noexcept
845 { return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; }
846
847 bool
848 _M_less(const __weak_count& __rhs) const noexcept
849 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
850
851 bool
852 _M_less(const __shared_count<_Lp>& __rhs) const noexcept
853 { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
854
855 // Friend function injected into enclosing namespace and found by ADL
856 friend inline bool
857 operator==(const __weak_count& __a, const __weak_count& __b) noexcept
858 { return __a._M_pi == __b._M_pi; }
859
860 private:
861 friend class __shared_count<_Lp>;
862
863 _Sp_counted_base<_Lp>* _M_pi;
864 };
865
866 // Now that __weak_count is defined we can define this constructor:
867 template<_Lock_policy _Lp>
868 inline
869 __shared_count<_Lp>::__shared_count(const __weak_count<_Lp>& __r)
870 : _M_pi(__r._M_pi)
871 {
872 if (_M_pi == nullptr || !_M_pi->_M_add_ref_lock_nothrow())
873 __throw_bad_weak_ptr();
874 }
875
876 // Now that __weak_count is defined we can define this constructor:
877 template<_Lock_policy _Lp>
878 inline
879 __shared_count<_Lp>::
880 __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t) noexcept
881 : _M_pi(__r._M_pi)
882 {
883 if (_M_pi && !_M_pi->_M_add_ref_lock_nothrow())
884 _M_pi = nullptr;
885 }
886
887#define __cpp_lib_shared_ptr_arrays 201611L
888
889 // Helper traits for shared_ptr of array:
890
891 // A pointer type Y* is said to be compatible with a pointer type T* when
892 // either Y* is convertible to T* or Y is U[N] and T is U cv [].
893 template<typename _Yp_ptr, typename _Tp_ptr>
894 struct __sp_compatible_with
895 : false_type
896 { };
897
898 template<typename _Yp, typename _Tp>
899 struct __sp_compatible_with<_Yp*, _Tp*>
900 : is_convertible<_Yp*, _Tp*>::type
901 { };
902
903 template<typename _Up, size_t _Nm>
904 struct __sp_compatible_with<_Up(*)[_Nm], _Up(*)[]>
905 : true_type
906 { };
907
908 template<typename _Up, size_t _Nm>
909 struct __sp_compatible_with<_Up(*)[_Nm], const _Up(*)[]>
910 : true_type
911 { };
912
913 template<typename _Up, size_t _Nm>
914 struct __sp_compatible_with<_Up(*)[_Nm], volatile _Up(*)[]>
915 : true_type
916 { };
917
918 template<typename _Up, size_t _Nm>
919 struct __sp_compatible_with<_Up(*)[_Nm], const volatile _Up(*)[]>
920 : true_type
921 { };
922
923 // Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N].
924 template<typename _Up, size_t _Nm, typename _Yp, typename = void>
925 struct __sp_is_constructible_arrN
926 : false_type
927 { };
928
929 template<typename _Up, size_t _Nm, typename _Yp>
930 struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>>
931 : is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type
932 { };
933
934 // Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[].
935 template<typename _Up, typename _Yp, typename = void>
936 struct __sp_is_constructible_arr
937 : false_type
938 { };
939
940 template<typename _Up, typename _Yp>
941 struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>>
942 : is_convertible<_Yp(*)[], _Up(*)[]>::type
943 { };
944
945 // Trait to check if shared_ptr<T> can be constructed from Y*.
946 template<typename _Tp, typename _Yp>
947 struct __sp_is_constructible;
948
949 // When T is U[N], Y(*)[N] shall be convertible to T*;
950 template<typename _Up, size_t _Nm, typename _Yp>
951 struct __sp_is_constructible<_Up[_Nm], _Yp>
952 : __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type
953 { };
954
955 // when T is U[], Y(*)[] shall be convertible to T*;
956 template<typename _Up, typename _Yp>
957 struct __sp_is_constructible<_Up[], _Yp>
958 : __sp_is_constructible_arr<_Up, _Yp>::type
959 { };
960
961 // otherwise, Y* shall be convertible to T*.
962 template<typename _Tp, typename _Yp>
963 struct __sp_is_constructible
964 : is_convertible<_Yp*, _Tp*>::type
965 { };
966
967
968 // Define operator* and operator-> for shared_ptr<T>.
969 template<typename _Tp, _Lock_policy _Lp,
970 bool = is_array<_Tp>::value, bool = is_void<_Tp>::value>
971 class __shared_ptr_access
972 {
973 public:
974 using element_type = _Tp;
975
976 element_type&
977 operator*() const noexcept
978 {
979 __glibcxx_assert(_M_get() != nullptr);
980 return *_M_get();
981 }
982
983 element_type*
984 operator->() const noexcept
985 {
986 _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
987 return _M_get();
988 }
989
990 private:
991 element_type*
992 _M_get() const noexcept
993 { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }
994 };
995
996 // Define operator-> for shared_ptr<cv void>.
997 template<typename _Tp, _Lock_policy _Lp>
998 class __shared_ptr_access<_Tp, _Lp, false, true>
999 {
1000 public:
1001 using element_type = _Tp;
1002
1003 element_type*
1004 operator->() const noexcept
1005 {
1006 auto __ptr = static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get();
1007 _GLIBCXX_DEBUG_PEDASSERT(__ptr != nullptr);
1008 return __ptr;
1009 }
1010 };
1011
1012 // Define operator[] for shared_ptr<T[]> and shared_ptr<T[N]>.
1013 template<typename _Tp, _Lock_policy _Lp>
1014 class __shared_ptr_access<_Tp, _Lp, true, false>
1015 {
1016 public:
1017 using element_type = typename remove_extent<_Tp>::type;
1018
1019#if __cplusplus <= 201402L
1020 [[__deprecated__("shared_ptr<T[]>::operator* is absent from C++17")]]
1021 element_type&
1022 operator*() const noexcept
1023 {
1024 __glibcxx_assert(_M_get() != nullptr);
1025 return *_M_get();
1026 }
1027
1028 [[__deprecated__("shared_ptr<T[]>::operator-> is absent from C++17")]]
1029 element_type*
1030 operator->() const noexcept
1031 {
1032 _GLIBCXX_DEBUG_PEDASSERT(_M_get() != nullptr);
1033 return _M_get();
1034 }
1035#endif
1036
1037 element_type&
1038 operator[](ptrdiff_t __i) const
1039 {
1040 __glibcxx_assert(_M_get() != nullptr);
1041 __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value);
1042 return _M_get()[__i];
1043 }
1044
1045 private:
1046 element_type*
1047 _M_get() const noexcept
1048 { return static_cast<const __shared_ptr<_Tp, _Lp>*>(this)->get(); }
1049 };
1050
1051 template<typename _Tp, _Lock_policy _Lp>
1052 class __shared_ptr
1053 : public __shared_ptr_access<_Tp, _Lp>
1054 {
1055 public:
1056 using element_type = typename remove_extent<_Tp>::type;
1057
1058 private:
1059 // Constraint for taking ownership of a pointer of type _Yp*:
1060 template<typename _Yp>
1061 using _SafeConv
1062 = typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type;
1063
1064 // Constraint for construction from shared_ptr and weak_ptr:
1065 template<typename _Yp, typename _Res = void>
1066 using _Compatible = typename
1067 enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
1068
1069 // Constraint for assignment from shared_ptr and weak_ptr:
1070 template<typename _Yp>
1071 using _Assignable = _Compatible<_Yp, __shared_ptr&>;
1072
1073 // Constraint for construction from unique_ptr:
1074 template<typename _Yp, typename _Del, typename _Res = void,
1075 typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer>
1076 using _UniqCompatible = __enable_if_t<__and_<
1077 __sp_compatible_with<_Yp*, _Tp*>,
1078 is_convertible<_Ptr, element_type*>,
1079 is_move_constructible<_Del>
1080 >::value, _Res>;
1081
1082 // Constraint for assignment from unique_ptr:
1083 template<typename _Yp, typename _Del>
1084 using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>;
1085
1086 public:
1087
1088#if __cplusplus > 201402L
1089 using weak_type = __weak_ptr<_Tp, _Lp>;
1090#endif
1091
1092 constexpr __shared_ptr() noexcept
1093 : _M_ptr(0), _M_refcount()
1094 { }
1095
1096 template<typename _Yp, typename = _SafeConv<_Yp>>
1097 explicit
1098 __shared_ptr(_Yp* __p)
1099 : _M_ptr(__p), _M_refcount(__p, typename is_array<_Tp>::type())
1100 {
1101 static_assert( !is_void<_Yp>::value, "incomplete type" );
1102 static_assert( sizeof(_Yp) > 0, "incomplete type" );
1103 _M_enable_shared_from_this_with(__p);
1104 }
1105
1106 template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>>
1107 __shared_ptr(_Yp* __p, _Deleter __d)
1108 : _M_ptr(__p), _M_refcount(__p, std::move(__d))
1109 {
1110 static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
1111 "deleter expression d(p) is well-formed");
1112 _M_enable_shared_from_this_with(__p);
1113 }
1114
1115 template<typename _Yp, typename _Deleter, typename _Alloc,
1116 typename = _SafeConv<_Yp>>
1117 __shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
1118 : _M_ptr(__p), _M_refcount(__p, std::move(__d), std::move(__a))
1119 {
1120 static_assert(__is_invocable<_Deleter&, _Yp*&>::value,
1121 "deleter expression d(p) is well-formed");
1122 _M_enable_shared_from_this_with(__p);
1123 }
1124
1125 template<typename _Deleter>
1126 __shared_ptr(nullptr_t __p, _Deleter __d)
1127 : _M_ptr(0), _M_refcount(__p, std::move(__d))
1128 { }
1129
1130 template<typename _Deleter, typename _Alloc>
1131 __shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
1132 : _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a))
1133 { }
1134
1135 // Aliasing constructor
1136 template<typename _Yp>
1137 __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r,
1138 element_type* __p) noexcept
1139 : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
1140 { }
1141
1142 // Aliasing constructor
1143 template<typename _Yp>
1144 __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r,
1145 element_type* __p) noexcept
1146 : _M_ptr(__p), _M_refcount()
1147 {
1148 _M_refcount._M_swap(__r._M_refcount);
1149 __r._M_ptr = nullptr;
1150 }
1151
1152 __shared_ptr(const __shared_ptr&) noexcept = default;
1153 __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
1154 ~__shared_ptr() = default;
1155
1156 template<typename _Yp, typename = _Compatible<_Yp>>
1157 __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1158 : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
1159 { }
1160
1161 __shared_ptr(__shared_ptr&& __r) noexcept
1162 : _M_ptr(__r._M_ptr), _M_refcount()
1163 {
1164 _M_refcount._M_swap(__r._M_refcount);
1165 __r._M_ptr = nullptr;
1166 }
1167
1168 template<typename _Yp, typename = _Compatible<_Yp>>
1169 __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept
1170 : _M_ptr(__r._M_ptr), _M_refcount()
1171 {
1172 _M_refcount._M_swap(__r._M_refcount);
1173 __r._M_ptr = nullptr;
1174 }
1175
1176 template<typename _Yp, typename = _Compatible<_Yp>>
1177 explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r)
1178 : _M_refcount(__r._M_refcount) // may throw
1179 {
1180 // It is now safe to copy __r._M_ptr, as
1181 // _M_refcount(__r._M_refcount) did not throw.
1182 _M_ptr = __r._M_ptr;
1183 }
1184
1185 // If an exception is thrown this constructor has no effect.
1186 template<typename _Yp, typename _Del,
1187 typename = _UniqCompatible<_Yp, _Del>>
1188 __shared_ptr(unique_ptr<_Yp, _Del>&& __r)
1189 : _M_ptr(__r.get()), _M_refcount()
1190 {
1191 auto __raw = __to_address(__r.get());
1192 _M_refcount = __shared_count<_Lp>(std::move(__r));
1193 _M_enable_shared_from_this_with(__raw);
1194 }
1195
1196#if __cplusplus <= 201402L && _GLIBCXX_USE_DEPRECATED
1197 protected:
1198 // If an exception is thrown this constructor has no effect.
1199 template<typename _Tp1, typename _Del,
1200 typename enable_if<__and_<
1201 __not_<is_array<_Tp>>, is_array<_Tp1>,
1202 is_convertible<typename unique_ptr<_Tp1, _Del>::pointer, _Tp*>
1203 >::value, bool>::type = true>
1204 __shared_ptr(unique_ptr<_Tp1, _Del>&& __r, __sp_array_delete)
1205 : _M_ptr(__r.get()), _M_refcount()
1206 {
1207 auto __raw = __to_address(__r.get());
1208 _M_refcount = __shared_count<_Lp>(std::move(__r));
1209 _M_enable_shared_from_this_with(__raw);
1210 }
1211 public:
1212#endif
1213
1214#if _GLIBCXX_USE_DEPRECATED
1215#pragma GCC diagnostic push
1216#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1217 // Postcondition: use_count() == 1 and __r.get() == 0
1218 template<typename _Yp, typename = _Compatible<_Yp>>
1219 __shared_ptr(auto_ptr<_Yp>&& __r);
1220#pragma GCC diagnostic pop
1221#endif
1222
1223 constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
1224
1225 template<typename _Yp>
1226 _Assignable<_Yp>
1227 operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1228 {
1229 _M_ptr = __r._M_ptr;
1230 _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
1231 return *this;
1232 }
1233
1234#if _GLIBCXX_USE_DEPRECATED
1235#pragma GCC diagnostic push
1236#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1237 template<typename _Yp>
1238 _Assignable<_Yp>
1239 operator=(auto_ptr<_Yp>&& __r)
1240 {
1241 __shared_ptr(std::move(__r)).swap(*this);
1242 return *this;
1243 }
1244#pragma GCC diagnostic pop
1245#endif
1246
1247 __shared_ptr&
1248 operator=(__shared_ptr&& __r) noexcept
1249 {
1250 __shared_ptr(std::move(__r)).swap(*this);
1251 return *this;
1252 }
1253
1254 template<class _Yp>
1255 _Assignable<_Yp>
1256 operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept
1257 {
1258 __shared_ptr(std::move(__r)).swap(*this);
1259 return *this;
1260 }
1261
1262 template<typename _Yp, typename _Del>
1263 _UniqAssignable<_Yp, _Del>
1264 operator=(unique_ptr<_Yp, _Del>&& __r)
1265 {
1266 __shared_ptr(std::move(__r)).swap(*this);
1267 return *this;
1268 }
1269
1270 void
1271 reset() noexcept
1272 { __shared_ptr().swap(*this); }
1273
1274 template<typename _Yp>
1275 _SafeConv<_Yp>
1276 reset(_Yp* __p) // _Yp must be complete.
1277 {
1278 // Catch self-reset errors.
1279 __glibcxx_assert(__p == nullptr || __p != _M_ptr);
1280 __shared_ptr(__p).swap(*this);
1281 }
1282
1283 template<typename _Yp, typename _Deleter>
1284 _SafeConv<_Yp>
1285 reset(_Yp* __p, _Deleter __d)
1286 { __shared_ptr(__p, std::move(__d)).swap(*this); }
1287
1288 template<typename _Yp, typename _Deleter, typename _Alloc>
1289 _SafeConv<_Yp>
1290 reset(_Yp* __p, _Deleter __d, _Alloc __a)
1291 { __shared_ptr(__p, std::move(__d), std::move(__a)).swap(*this); }
1292
1293 /// Return the stored pointer.
1294 element_type*
1295 get() const noexcept
1296 { return _M_ptr; }
1297
1298 /// Return true if the stored pointer is not null.
1299 explicit operator bool() const noexcept
1300 { return _M_ptr != nullptr; }
1301
1302 /// Return true if use_count() == 1.
1303 bool
1304 unique() const noexcept
1305 { return _M_refcount._M_unique(); }
1306
1307 /// If *this owns a pointer, return the number of owners, otherwise zero.
1308 long
1309 use_count() const noexcept
1310 { return _M_refcount._M_get_use_count(); }
1311
1312 /// Exchange both the owned pointer and the stored pointer.
1313 void
1314 swap(__shared_ptr<_Tp, _Lp>& __other) noexcept
1315 {
1316 std::swap(_M_ptr, __other._M_ptr);
1317 _M_refcount._M_swap(__other._M_refcount);
1318 }
1319
1320 /** @brief Define an ordering based on ownership.
1321 *
1322 * This function defines a strict weak ordering between two shared_ptr
1323 * or weak_ptr objects, such that one object is less than the other
1324 * unless they share ownership of the same pointer, or are both empty.
1325 * @{
1326 */
1327 template<typename _Tp1>
1328 bool
1329 owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept
1330 { return _M_refcount._M_less(__rhs._M_refcount); }
1331
1332 template<typename _Tp1>
1333 bool
1334 owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept
1335 { return _M_refcount._M_less(__rhs._M_refcount); }
1336 /// @}
1337
1338 protected:
1339 // This constructor is non-standard, it is used by allocate_shared.
1340 template<typename _Alloc, typename... _Args>
1341 __shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
1342 : _M_ptr(), _M_refcount(_M_ptr, __tag, std::forward<_Args>(__args)...)
1343 { _M_enable_shared_from_this_with(_M_ptr); }
1344
1345 template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc,
1346 typename... _Args>
1347 friend __shared_ptr<_Tp1, _Lp1>
1348 __allocate_shared(const _Alloc& __a, _Args&&... __args);
1349
1350 // This constructor is used by __weak_ptr::lock() and
1351 // shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t).
1352 __shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t) noexcept
1353 : _M_refcount(__r._M_refcount, std::nothrow)
1354 {
1355 _M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr;
1356 }
1357
1358 friend class __weak_ptr<_Tp, _Lp>;
1359
1360 private:
1361
1362 template<typename _Yp>
1363 using __esft_base_t = decltype(__enable_shared_from_this_base(
1364 std::declval<const __shared_count<_Lp>&>(),
1365 std::declval<_Yp*>()));
1366
1367 // Detect an accessible and unambiguous enable_shared_from_this base.
1368 template<typename _Yp, typename = void>
1369 struct __has_esft_base
1370 : false_type { };
1371
1372 template<typename _Yp>
1373 struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>>
1374 : __not_<is_array<_Tp>> { }; // No enable shared_from_this for arrays
1375
1376 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
1377 typename enable_if<__has_esft_base<_Yp2>::value>::type
1378 _M_enable_shared_from_this_with(_Yp* __p) noexcept
1379 {
1380 if (auto __base = __enable_shared_from_this_base(_M_refcount, __p))
1381 __base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount);
1382 }
1383
1384 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
1385 typename enable_if<!__has_esft_base<_Yp2>::value>::type
1386 _M_enable_shared_from_this_with(_Yp*) noexcept
1387 { }
1388
1389 void*
1390 _M_get_deleter(const std::type_info& __ti) const noexcept
1391 { return _M_refcount._M_get_deleter(__ti); }
1392
1393 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
1394 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
1395
1396 template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
1397 friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
1398
1399 template<typename _Del, typename _Tp1>
1400 friend _Del* get_deleter(const shared_ptr<_Tp1>&) noexcept;
1401
1402 element_type* _M_ptr; // Contained pointer.
1403 __shared_count<_Lp> _M_refcount; // Reference counter.
1404 };
1405
1406
1407 // 20.7.2.2.7 shared_ptr comparisons
1408 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1409 inline bool
1410 operator==(const __shared_ptr<_Tp1, _Lp>& __a,
1411 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1412 { return __a.get() == __b.get(); }
1413
1414 template<typename _Tp, _Lock_policy _Lp>
1415 inline bool
1416 operator==(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1417 { return !__a; }
1418
1419#ifdef __cpp_lib_three_way_comparison
1420 template<typename _Tp, typename _Up, _Lock_policy _Lp>
1421 inline strong_ordering
1422 operator<=>(const __shared_ptr<_Tp, _Lp>& __a,
1423 const __shared_ptr<_Up, _Lp>& __b) noexcept
1424 { return compare_three_way()(__a.get(), __b.get()); }
1425
1426 template<typename _Tp, _Lock_policy _Lp>
1427 inline strong_ordering
1428 operator<=>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1429 {
1430 using pointer = typename __shared_ptr<_Tp, _Lp>::element_type*;
1431 return compare_three_way()(__a.get(), static_cast<pointer>(nullptr));
1432 }
1433#else
1434 template<typename _Tp, _Lock_policy _Lp>
1435 inline bool
1436 operator==(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1437 { return !__a; }
1438
1439 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1440 inline bool
1441 operator!=(const __shared_ptr<_Tp1, _Lp>& __a,
1442 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1443 { return __a.get() != __b.get(); }
1444
1445 template<typename _Tp, _Lock_policy _Lp>
1446 inline bool
1447 operator!=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1448 { return (bool)__a; }
1449
1450 template<typename _Tp, _Lock_policy _Lp>
1451 inline bool
1452 operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1453 { return (bool)__a; }
1454
1455 template<typename _Tp, typename _Up, _Lock_policy _Lp>
1456 inline bool
1457 operator<(const __shared_ptr<_Tp, _Lp>& __a,
1458 const __shared_ptr<_Up, _Lp>& __b) noexcept
1459 {
1460 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1461 using _Up_elt = typename __shared_ptr<_Up, _Lp>::element_type;
1462 using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
1463 return less<_Vp>()(__a.get(), __b.get());
1464 }
1465
1466 template<typename _Tp, _Lock_policy _Lp>
1467 inline bool
1468 operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1469 {
1470 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1471 return less<_Tp_elt*>()(__a.get(), nullptr);
1472 }
1473
1474 template<typename _Tp, _Lock_policy _Lp>
1475 inline bool
1476 operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1477 {
1478 using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
1479 return less<_Tp_elt*>()(nullptr, __a.get());
1480 }
1481
1482 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1483 inline bool
1484 operator<=(const __shared_ptr<_Tp1, _Lp>& __a,
1485 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1486 { return !(__b < __a); }
1487
1488 template<typename _Tp, _Lock_policy _Lp>
1489 inline bool
1490 operator<=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1491 { return !(nullptr < __a); }
1492
1493 template<typename _Tp, _Lock_policy _Lp>
1494 inline bool
1495 operator<=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1496 { return !(__a < nullptr); }
1497
1498 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1499 inline bool
1500 operator>(const __shared_ptr<_Tp1, _Lp>& __a,
1501 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1502 { return (__b < __a); }
1503
1504 template<typename _Tp, _Lock_policy _Lp>
1505 inline bool
1506 operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1507 { return nullptr < __a; }
1508
1509 template<typename _Tp, _Lock_policy _Lp>
1510 inline bool
1511 operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1512 { return __a < nullptr; }
1513
1514 template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
1515 inline bool
1516 operator>=(const __shared_ptr<_Tp1, _Lp>& __a,
1517 const __shared_ptr<_Tp2, _Lp>& __b) noexcept
1518 { return !(__a < __b); }
1519
1520 template<typename _Tp, _Lock_policy _Lp>
1521 inline bool
1522 operator>=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
1523 { return !(__a < nullptr); }
1524
1525 template<typename _Tp, _Lock_policy _Lp>
1526 inline bool
1527 operator>=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
1528 { return !(nullptr < __a); }
1529#endif // three-way comparison
1530
1531 // 20.7.2.2.8 shared_ptr specialized algorithms.
1532 template<typename _Tp, _Lock_policy _Lp>
1533 inline void
1534 swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) noexcept
1535 { __a.swap(__b); }
1536
1537 // 20.7.2.2.9 shared_ptr casts
1538
1539 // The seemingly equivalent code:
1540 // shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))
1541 // will eventually result in undefined behaviour, attempting to
1542 // delete the same object twice.
1543 /// static_pointer_cast
1544 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1545 inline __shared_ptr<_Tp, _Lp>
1546 static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1547 {
1548 using _Sp = __shared_ptr<_Tp, _Lp>;
1549 return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
1550 }
1551
1552 // The seemingly equivalent code:
1553 // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
1554 // will eventually result in undefined behaviour, attempting to
1555 // delete the same object twice.
1556 /// const_pointer_cast
1557 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1558 inline __shared_ptr<_Tp, _Lp>
1559 const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1560 {
1561 using _Sp = __shared_ptr<_Tp, _Lp>;
1562 return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
1563 }
1564
1565 // The seemingly equivalent code:
1566 // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
1567 // will eventually result in undefined behaviour, attempting to
1568 // delete the same object twice.
1569 /// dynamic_pointer_cast
1570 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1571 inline __shared_ptr<_Tp, _Lp>
1572 dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1573 {
1574 using _Sp = __shared_ptr<_Tp, _Lp>;
1575 if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
1576 return _Sp(__r, __p);
1577 return _Sp();
1578 }
1579
1580#if __cplusplus > 201402L
1581 template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
1582 inline __shared_ptr<_Tp, _Lp>
1583 reinterpret_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
1584 {
1585 using _Sp = __shared_ptr<_Tp, _Lp>;
1586 return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
1587 }
1588#endif
1589
1590 template<typename _Tp, _Lock_policy _Lp>
1591 class __weak_ptr
1592 {
1593 template<typename _Yp, typename _Res = void>
1594 using _Compatible = typename
1595 enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
1596
1597 // Constraint for assignment from shared_ptr and weak_ptr:
1598 template<typename _Yp>
1599 using _Assignable = _Compatible<_Yp, __weak_ptr&>;
1600
1601 public:
1602 using element_type = typename remove_extent<_Tp>::type;
1603
1604 constexpr __weak_ptr() noexcept
1605 : _M_ptr(nullptr), _M_refcount()
1606 { }
1607
1608 __weak_ptr(const __weak_ptr&) noexcept = default;
1609
1610 ~__weak_ptr() = default;
1611
1612 // The "obvious" converting constructor implementation:
1613 //
1614 // template<typename _Tp1>
1615 // __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
1616 // : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
1617 // { }
1618 //
1619 // has a serious problem.
1620 //
1621 // __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr)
1622 // conversion may require access to *__r._M_ptr (virtual inheritance).
1623 //
1624 // It is not possible to avoid spurious access violations since
1625 // in multithreaded programs __r._M_ptr may be invalidated at any point.
1626 template<typename _Yp, typename = _Compatible<_Yp>>
1627 __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept
1628 : _M_refcount(__r._M_refcount)
1629 { _M_ptr = __r.lock().get(); }
1630
1631 template<typename _Yp, typename = _Compatible<_Yp>>
1632 __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1633 : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
1634 { }
1635
1636 __weak_ptr(__weak_ptr&& __r) noexcept
1637 : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount))
1638 { __r._M_ptr = nullptr; }
1639
1640 template<typename _Yp, typename = _Compatible<_Yp>>
1641 __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept
1642 : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
1643 { __r._M_ptr = nullptr; }
1644
1645 __weak_ptr&
1646 operator=(const __weak_ptr& __r) noexcept = default;
1647
1648 template<typename _Yp>
1649 _Assignable<_Yp>
1650 operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept
1651 {
1652 _M_ptr = __r.lock().get();
1653 _M_refcount = __r._M_refcount;
1654 return *this;
1655 }
1656
1657 template<typename _Yp>
1658 _Assignable<_Yp>
1659 operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
1660 {
1661 _M_ptr = __r._M_ptr;
1662 _M_refcount = __r._M_refcount;
1663 return *this;
1664 }
1665
1666 __weak_ptr&
1667 operator=(__weak_ptr&& __r) noexcept
1668 {
1669 _M_ptr = __r._M_ptr;
1670 _M_refcount = std::move(__r._M_refcount);
1671 __r._M_ptr = nullptr;
1672 return *this;
1673 }
1674
1675 template<typename _Yp>
1676 _Assignable<_Yp>
1677 operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept
1678 {
1679 _M_ptr = __r.lock().get();
1680 _M_refcount = std::move(__r._M_refcount);
1681 __r._M_ptr = nullptr;
1682 return *this;
1683 }
1684
1685 __shared_ptr<_Tp, _Lp>
1686 lock() const noexcept
1687 { return __shared_ptr<element_type, _Lp>(*this, std::nothrow); }
1688
1689 long
1690 use_count() const noexcept
1691 { return _M_refcount._M_get_use_count(); }
1692
1693 bool
1694 expired() const noexcept
1695 { return _M_refcount._M_get_use_count() == 0; }
1696
1697 template<typename _Tp1>
1698 bool
1699 owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const noexcept
1700 { return _M_refcount._M_less(__rhs._M_refcount); }
1701
1702 template<typename _Tp1>
1703 bool
1704 owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept
1705 { return _M_refcount._M_less(__rhs._M_refcount); }
1706
1707 void
1708 reset() noexcept
1709 { __weak_ptr().swap(*this); }
1710
1711 void
1712 swap(__weak_ptr& __s) noexcept
1713 {
1714 std::swap(_M_ptr, __s._M_ptr);
1715 _M_refcount._M_swap(__s._M_refcount);
1716 }
1717
1718 private:
1719 // Used by __enable_shared_from_this.
1720 void
1721 _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) noexcept
1722 {
1723 if (use_count() == 0)
1724 {
1725 _M_ptr = __ptr;
1726 _M_refcount = __refcount;
1727 }
1728 }
1729
1730 template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
1731 template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
1732 friend class __enable_shared_from_this<_Tp, _Lp>;
1733 friend class enable_shared_from_this<_Tp>;
1734
1735 element_type* _M_ptr; // Contained pointer.
1736 __weak_count<_Lp> _M_refcount; // Reference counter.
1737 };
1738
1739 // 20.7.2.3.6 weak_ptr specialized algorithms.
1740 template<typename _Tp, _Lock_policy _Lp>
1741 inline void
1742 swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) noexcept
1743 { __a.swap(__b); }
1744
1745 template<typename _Tp, typename _Tp1>
1746 struct _Sp_owner_less : public binary_function<_Tp, _Tp, bool>
1747 {
1748 bool
1749 operator()(const _Tp& __lhs, const _Tp& __rhs) const noexcept
1750 { return __lhs.owner_before(__rhs); }
1751
1752 bool
1753 operator()(const _Tp& __lhs, const _Tp1& __rhs) const noexcept
1754 { return __lhs.owner_before(__rhs); }
1755
1756 bool
1757 operator()(const _Tp1& __lhs, const _Tp& __rhs) const noexcept
1758 { return __lhs.owner_before(__rhs); }
1759 };
1760
1761 template<>
1762 struct _Sp_owner_less<void, void>
1763 {
1764 template<typename _Tp, typename _Up>
1765 auto
1766 operator()(const _Tp& __lhs, const _Up& __rhs) const noexcept
1767 -> decltype(__lhs.owner_before(__rhs))
1768 { return __lhs.owner_before(__rhs); }
1769
1770 using is_transparent = void;
1771 };
1772
1773 template<typename _Tp, _Lock_policy _Lp>
1774 struct owner_less<__shared_ptr<_Tp, _Lp>>
1775 : public _Sp_owner_less<__shared_ptr<_Tp, _Lp>, __weak_ptr<_Tp, _Lp>>
1776 { };
1777
1778 template<typename _Tp, _Lock_policy _Lp>
1779 struct owner_less<__weak_ptr<_Tp, _Lp>>
1780 : public _Sp_owner_less<__weak_ptr<_Tp, _Lp>, __shared_ptr<_Tp, _Lp>>
1781 { };
1782
1783
1784 template<typename _Tp, _Lock_policy _Lp>
1785 class __enable_shared_from_this
1786 {
1787 protected:
1788 constexpr __enable_shared_from_this() noexcept { }
1789
1790 __enable_shared_from_this(const __enable_shared_from_this&) noexcept { }
1791
1792 __enable_shared_from_this&
1793 operator=(const __enable_shared_from_this&) noexcept
1794 { return *this; }
1795
1796 ~__enable_shared_from_this() { }
1797
1798 public:
1799 __shared_ptr<_Tp, _Lp>
1800 shared_from_this()
1801 { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); }
1802
1803 __shared_ptr<const _Tp, _Lp>
1804 shared_from_this() const
1805 { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); }
1806
1807#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
1808 __weak_ptr<_Tp, _Lp>
1809 weak_from_this() noexcept
1810 { return this->_M_weak_this; }
1811
1812 __weak_ptr<const _Tp, _Lp>
1813 weak_from_this() const noexcept
1814 { return this->_M_weak_this; }
1815#endif
1816
1817 private:
1818 template<typename _Tp1>
1819 void
1820 _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const noexcept
1821 { _M_weak_this._M_assign(__p, __n); }
1822
1823 friend const __enable_shared_from_this*
1824 __enable_shared_from_this_base(const __shared_count<_Lp>&,
1825 const __enable_shared_from_this* __p)
1826 { return __p; }
1827
1828 template<typename, _Lock_policy>
1829 friend class __shared_ptr;
1830
1831 mutable __weak_ptr<_Tp, _Lp> _M_weak_this;
1832 };
1833
1834 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy,
1835 typename _Alloc, typename... _Args>
1836 inline __shared_ptr<_Tp, _Lp>
1837 __allocate_shared(const _Alloc& __a, _Args&&... __args)
1838 {
1839 static_assert(!is_array<_Tp>::value, "make_shared<T[]> not supported");
1840
1841 return __shared_ptr<_Tp, _Lp>(_Sp_alloc_shared_tag<_Alloc>{__a},
1842 std::forward<_Args>(__args)...);
1843 }
1844
1845 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy,
1846 typename... _Args>
1847 inline __shared_ptr<_Tp, _Lp>
1848 __make_shared(_Args&&... __args)
1849 {
1850 typedef typename std::remove_const<_Tp>::type _Tp_nc;
1851 return std::__allocate_shared<_Tp, _Lp>(std::allocator<_Tp_nc>(),
1852 std::forward<_Args>(__args)...);
1853 }
1854
1855 /// std::hash specialization for __shared_ptr.
1856 template<typename _Tp, _Lock_policy _Lp>
1857 struct hash<__shared_ptr<_Tp, _Lp>>
1858 : public __hash_base<size_t, __shared_ptr<_Tp, _Lp>>
1859 {
1860 size_t
1861 operator()(const __shared_ptr<_Tp, _Lp>& __s) const noexcept
1862 {
1863 return hash<typename __shared_ptr<_Tp, _Lp>::element_type*>()(
1864 __s.get());
1865 }
1866 };
1867
1868_GLIBCXX_END_NAMESPACE_VERSION
1869} // namespace
1870
1871#endif // _SHARED_PTR_BASE_H
Note: See TracBrowser for help on using the repository browser.