1 // <tr1/shared_ptr.h> -*- C++ -*-
3 // Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc.
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 // <http://www.gnu.org/licenses/>.
27 // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
30 // Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
31 // Copyright (C) 2001, 2002, 2003 Peter Dimov
34 // Copyright (C) 2001, 2002, 2003 Peter Dimov
36 // enable_shared_from_this.hpp
37 // Copyright (C) 2002 Peter Dimov
39 // Distributed under the Boost Software License, Version 1.0. (See
40 // accompanying file LICENSE_1_0.txt or copy at
41 // http://www.boost.org/LICENSE_1_0.txt)
43 // GCC Note: based on version 1.32.0 of the Boost library.
45 /** @file tr1/shared_ptr.h
46 * This is an internal header file, included by other library headers.
47 * Do not attempt to use it directly. @headername{tr1/memory}
50 #ifndef _TR1_SHARED_PTR_H
51 #define _TR1_SHARED_PTR_H 1
53 namespace std
_GLIBCXX_VISIBILITY(default)
57 _GLIBCXX_BEGIN_NAMESPACE_VERSION
60 * @brief Exception possibly thrown by @c shared_ptr.
63 class bad_weak_ptr
: public std::exception
68 { return "tr1::bad_weak_ptr"; }
71 // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
73 __throw_bad_weak_ptr()
82 using __gnu_cxx::_Lock_policy
;
83 using __gnu_cxx::__default_lock_policy
;
84 using __gnu_cxx::_S_single
;
85 using __gnu_cxx::_S_mutex
;
86 using __gnu_cxx::_S_atomic
;
88 // Empty helper class except when the template argument is _S_mutex.
89 template<_Lock_policy _Lp
>
93 // The atomic policy uses fully-fenced builtins, single doesn't care.
94 enum { _S_need_barriers
= 0 };
98 class _Mutex_base
<_S_mutex
>
99 : public __gnu_cxx::__mutex
102 // This policy is used when atomic builtins are not available.
103 // The replacement atomic operations might not have the necessary
105 enum { _S_need_barriers
= 1 };
108 template<_Lock_policy _Lp
= __default_lock_policy
>
109 class _Sp_counted_base
110 : public _Mutex_base
<_Lp
>
114 : _M_use_count(1), _M_weak_count(1) { }
117 ~_Sp_counted_base() // nothrow
120 // Called when _M_use_count drops to zero, to release the resources
123 _M_dispose() = 0; // nothrow
125 // Called when _M_weak_count drops to zero.
127 _M_destroy() // nothrow
131 _M_get_deleter(const std::type_info
&) = 0;
135 { __gnu_cxx::__atomic_add_dispatch(&_M_use_count
, 1); }
141 _M_release() // nothrow
143 // Be race-detector-friendly. For more info see bits/c++config.
144 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count
);
145 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count
, -1) == 1)
147 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count
);
149 // There must be a memory barrier between dispose() and destroy()
150 // to ensure that the effects of dispose() are observed in the
151 // thread that runs destroy().
152 // See http://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
153 if (_Mutex_base
<_Lp
>::_S_need_barriers
)
155 _GLIBCXX_READ_MEM_BARRIER
;
156 _GLIBCXX_WRITE_MEM_BARRIER
;
159 // Be race-detector-friendly. For more info see bits/c++config.
160 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count
);
161 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count
,
164 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count
);
171 _M_weak_add_ref() // nothrow
172 { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count
, 1); }
175 _M_weak_release() // nothrow
177 // Be race-detector-friendly. For more info see bits/c++config.
178 _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count
);
179 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count
, -1) == 1)
181 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count
);
182 if (_Mutex_base
<_Lp
>::_S_need_barriers
)
185 // destroy() must observe results of dispose()
186 _GLIBCXX_READ_MEM_BARRIER
;
187 _GLIBCXX_WRITE_MEM_BARRIER
;
194 _M_get_use_count() const // nothrow
196 // No memory barrier is used here so there is no synchronization
197 // with other threads.
198 return const_cast<const volatile _Atomic_word
&>(_M_use_count
);
202 _Sp_counted_base(_Sp_counted_base
const&);
203 _Sp_counted_base
& operator=(_Sp_counted_base
const&);
205 _Atomic_word _M_use_count
; // #shared
206 _Atomic_word _M_weak_count
; // #weak + (#shared != 0)
211 _Sp_counted_base
<_S_single
>::
214 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count
, 1) == 0)
217 __throw_bad_weak_ptr();
223 _Sp_counted_base
<_S_mutex
>::
226 __gnu_cxx::__scoped_lock
sentry(*this);
227 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count
, 1) == 0)
230 __throw_bad_weak_ptr();
236 _Sp_counted_base
<_S_atomic
>::
239 // Perform lock-free add-if-not-zero operation.
240 _Atomic_word __count
= _M_use_count
;
244 __throw_bad_weak_ptr();
245 // Replace the current counter value with the old value + 1, as
246 // long as it's not changed meanwhile.
248 while (!__atomic_compare_exchange_n(&_M_use_count
, &__count
, __count
+ 1,
249 true, __ATOMIC_ACQ_REL
,
253 template<typename _Ptr
, typename _Deleter
, _Lock_policy _Lp
>
254 class _Sp_counted_base_impl
255 : public _Sp_counted_base
<_Lp
>
258 // Precondition: __d(__p) must not throw.
259 _Sp_counted_base_impl(_Ptr __p
, _Deleter __d
)
260 : _M_ptr(__p
), _M_del(__d
) { }
263 _M_dispose() // nothrow
267 _M_get_deleter(const std::type_info
& __ti
)
270 return __ti
== typeid(_Deleter
) ? &_M_del
: 0;
277 _Sp_counted_base_impl(const _Sp_counted_base_impl
&);
278 _Sp_counted_base_impl
& operator=(const _Sp_counted_base_impl
&);
280 _Ptr _M_ptr
; // copy constructor must not throw
281 _Deleter _M_del
; // copy constructor must not throw
284 template<_Lock_policy _Lp
= __default_lock_policy
>
287 template<typename _Tp
>
290 typedef void result_type
;
291 typedef _Tp
* argument_type
;
292 void operator()(_Tp
* __p
) const { delete __p
; }
295 template<_Lock_policy _Lp
= __default_lock_policy
>
300 : _M_pi(0) // nothrow
303 template<typename _Ptr
>
304 __shared_count(_Ptr __p
) : _M_pi(0)
308 typedef typename
std::tr1::remove_pointer
<_Ptr
>::type _Tp
;
309 _M_pi
= new _Sp_counted_base_impl
<_Ptr
, _Sp_deleter
<_Tp
>, _Lp
>(
310 __p
, _Sp_deleter
<_Tp
>());
315 __throw_exception_again
;
319 template<typename _Ptr
, typename _Deleter
>
320 __shared_count(_Ptr __p
, _Deleter __d
) : _M_pi(0)
324 _M_pi
= new _Sp_counted_base_impl
<_Ptr
, _Deleter
, _Lp
>(__p
, __d
);
328 __d(__p
); // Call _Deleter on __p.
329 __throw_exception_again
;
333 // Special case for auto_ptr<_Tp> to provide the strong guarantee.
334 template<typename _Tp
>
336 __shared_count(std::auto_ptr
<_Tp
>& __r
)
337 : _M_pi(new _Sp_counted_base_impl
<_Tp
*,
338 _Sp_deleter
<_Tp
>, _Lp
>(__r
.get(), _Sp_deleter
<_Tp
>()))
341 // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
343 __shared_count(const __weak_count
<_Lp
>& __r
);
345 ~__shared_count() // nothrow
351 __shared_count(const __shared_count
& __r
)
352 : _M_pi(__r
._M_pi
) // nothrow
355 _M_pi
->_M_add_ref_copy();
359 operator=(const __shared_count
& __r
) // nothrow
361 _Sp_counted_base
<_Lp
>* __tmp
= __r
._M_pi
;
365 __tmp
->_M_add_ref_copy();
374 _M_swap(__shared_count
& __r
) // nothrow
376 _Sp_counted_base
<_Lp
>* __tmp
= __r
._M_pi
;
382 _M_get_use_count() const // nothrow
383 { return _M_pi
!= 0 ? _M_pi
->_M_get_use_count() : 0; }
386 _M_unique() const // nothrow
387 { return this->_M_get_use_count() == 1; }
390 operator==(const __shared_count
& __a
, const __shared_count
& __b
)
391 { return __a
._M_pi
== __b
._M_pi
; }
394 operator<(const __shared_count
& __a
, const __shared_count
& __b
)
395 { return std::less
<_Sp_counted_base
<_Lp
>*>()(__a
._M_pi
, __b
._M_pi
); }
398 _M_get_deleter(const std::type_info
& __ti
) const
399 { return _M_pi
? _M_pi
->_M_get_deleter(__ti
) : 0; }
402 friend class __weak_count
<_Lp
>;
404 _Sp_counted_base
<_Lp
>* _M_pi
;
408 template<_Lock_policy _Lp
>
413 : _M_pi(0) // nothrow
416 __weak_count(const __shared_count
<_Lp
>& __r
)
417 : _M_pi(__r
._M_pi
) // nothrow
420 _M_pi
->_M_weak_add_ref();
423 __weak_count(const __weak_count
<_Lp
>& __r
)
424 : _M_pi(__r
._M_pi
) // nothrow
427 _M_pi
->_M_weak_add_ref();
430 ~__weak_count() // nothrow
433 _M_pi
->_M_weak_release();
437 operator=(const __shared_count
<_Lp
>& __r
) // nothrow
439 _Sp_counted_base
<_Lp
>* __tmp
= __r
._M_pi
;
441 __tmp
->_M_weak_add_ref();
443 _M_pi
->_M_weak_release();
449 operator=(const __weak_count
<_Lp
>& __r
) // nothrow
451 _Sp_counted_base
<_Lp
>* __tmp
= __r
._M_pi
;
453 __tmp
->_M_weak_add_ref();
455 _M_pi
->_M_weak_release();
461 _M_swap(__weak_count
<_Lp
>& __r
) // nothrow
463 _Sp_counted_base
<_Lp
>* __tmp
= __r
._M_pi
;
469 _M_get_use_count() const // nothrow
470 { return _M_pi
!= 0 ? _M_pi
->_M_get_use_count() : 0; }
473 operator==(const __weak_count
<_Lp
>& __a
, const __weak_count
<_Lp
>& __b
)
474 { return __a
._M_pi
== __b
._M_pi
; }
477 operator<(const __weak_count
<_Lp
>& __a
, const __weak_count
<_Lp
>& __b
)
478 { return std::less
<_Sp_counted_base
<_Lp
>*>()(__a
._M_pi
, __b
._M_pi
); }
481 friend class __shared_count
<_Lp
>;
483 _Sp_counted_base
<_Lp
>* _M_pi
;
486 // now that __weak_count is defined we can define this constructor:
487 template<_Lock_policy _Lp
>
489 __shared_count
<_Lp
>::
490 __shared_count(const __weak_count
<_Lp
>& __r
)
494 _M_pi
->_M_add_ref_lock();
496 __throw_bad_weak_ptr();
499 // Forward declarations.
500 template<typename _Tp
, _Lock_policy _Lp
= __default_lock_policy
>
503 template<typename _Tp
, _Lock_policy _Lp
= __default_lock_policy
>
506 template<typename _Tp
, _Lock_policy _Lp
= __default_lock_policy
>
507 class __enable_shared_from_this
;
509 template<typename _Tp
>
512 template<typename _Tp
>
515 template<typename _Tp
>
516 class enable_shared_from_this
;
518 // Support for enable_shared_from_this.
520 // Friend of __enable_shared_from_this.
521 template<_Lock_policy _Lp
, typename _Tp1
, typename _Tp2
>
523 __enable_shared_from_this_helper(const __shared_count
<_Lp
>&,
524 const __enable_shared_from_this
<_Tp1
,
527 // Friend of enable_shared_from_this.
528 template<typename _Tp1
, typename _Tp2
>
530 __enable_shared_from_this_helper(const __shared_count
<>&,
531 const enable_shared_from_this
<_Tp1
>*,
534 template<_Lock_policy _Lp
>
536 __enable_shared_from_this_helper(const __shared_count
<_Lp
>&, ...)
540 struct __static_cast_tag
{ };
541 struct __const_cast_tag
{ };
542 struct __dynamic_cast_tag
{ };
544 // A smart pointer with reference-counted copy semantics. The
545 // object pointed to is deleted when the last shared_ptr pointing to
546 // it is destroyed or reset.
547 template<typename _Tp
, _Lock_policy _Lp
>
551 typedef _Tp element_type
;
554 : _M_ptr(0), _M_refcount() // never throws
557 template<typename _Tp1
>
559 __shared_ptr(_Tp1
* __p
)
560 : _M_ptr(__p
), _M_refcount(__p
)
562 __glibcxx_function_requires(_ConvertibleConcept
<_Tp1
*, _Tp
*>)
563 typedef int _IsComplete
[sizeof(_Tp1
)];
564 __enable_shared_from_this_helper(_M_refcount
, __p
, __p
);
567 template<typename _Tp1
, typename _Deleter
>
568 __shared_ptr(_Tp1
* __p
, _Deleter __d
)
569 : _M_ptr(__p
), _M_refcount(__p
, __d
)
571 __glibcxx_function_requires(_ConvertibleConcept
<_Tp1
*, _Tp
*>)
572 // TODO requires _Deleter CopyConstructible and __d(__p) well-formed
573 __enable_shared_from_this_helper(_M_refcount
, __p
, __p
);
576 // generated copy constructor, assignment, destructor are fine.
578 template<typename _Tp1
>
579 __shared_ptr(const __shared_ptr
<_Tp1
, _Lp
>& __r
)
580 : _M_ptr(__r
._M_ptr
), _M_refcount(__r
._M_refcount
) // never throws
581 { __glibcxx_function_requires(_ConvertibleConcept
<_Tp1
*, _Tp
*>) }
583 template<typename _Tp1
>
585 __shared_ptr(const __weak_ptr
<_Tp1
, _Lp
>& __r
)
586 : _M_refcount(__r
._M_refcount
) // may throw
588 __glibcxx_function_requires(_ConvertibleConcept
<_Tp1
*, _Tp
*>)
589 // It is now safe to copy __r._M_ptr, as _M_refcount(__r._M_refcount)
594 #if !defined(__GXX_EXPERIMENTAL_CXX0X__) || _GLIBCXX_USE_DEPRECATED
595 // Postcondition: use_count() == 1 and __r.get() == 0
596 template<typename _Tp1
>
598 __shared_ptr(std::auto_ptr
<_Tp1
>& __r
)
599 : _M_ptr(__r
.get()), _M_refcount()
600 { // TODO requries delete __r.release() well-formed
601 __glibcxx_function_requires(_ConvertibleConcept
<_Tp1
*, _Tp
*>)
602 typedef int _IsComplete
[sizeof(_Tp1
)];
603 _Tp1
* __tmp
= __r
.get();
604 _M_refcount
= __shared_count
<_Lp
>(__r
);
605 __enable_shared_from_this_helper(_M_refcount
, __tmp
, __tmp
);
610 template<typename _Tp1
>
611 __shared_ptr(const __shared_ptr
<_Tp1
, _Lp
>& __r
, __static_cast_tag
)
612 : _M_ptr(static_cast<element_type
*>(__r
._M_ptr
)),
613 _M_refcount(__r
._M_refcount
)
616 template<typename _Tp1
>
617 __shared_ptr(const __shared_ptr
<_Tp1
, _Lp
>& __r
, __const_cast_tag
)
618 : _M_ptr(const_cast<element_type
*>(__r
._M_ptr
)),
619 _M_refcount(__r
._M_refcount
)
622 template<typename _Tp1
>
623 __shared_ptr(const __shared_ptr
<_Tp1
, _Lp
>& __r
, __dynamic_cast_tag
)
624 : _M_ptr(dynamic_cast<element_type
*>(__r
._M_ptr
)),
625 _M_refcount(__r
._M_refcount
)
627 if (_M_ptr
== 0) // need to allocate new counter -- the cast failed
628 _M_refcount
= __shared_count
<_Lp
>();
631 template<typename _Tp1
>
633 operator=(const __shared_ptr
<_Tp1
, _Lp
>& __r
) // never throws
636 _M_refcount
= __r
._M_refcount
; // __shared_count::op= doesn't throw
640 #if !defined(__GXX_EXPERIMENTAL_CXX0X__) || _GLIBCXX_USE_DEPRECATED
641 template<typename _Tp1
>
643 operator=(std::auto_ptr
<_Tp1
>& __r
)
645 __shared_ptr(__r
).swap(*this);
651 reset() // never throws
652 { __shared_ptr().swap(*this); }
654 template<typename _Tp1
>
656 reset(_Tp1
* __p
) // _Tp1 must be complete.
658 // Catch self-reset errors.
659 _GLIBCXX_DEBUG_ASSERT(__p
== 0 || __p
!= _M_ptr
);
660 __shared_ptr(__p
).swap(*this);
663 template<typename _Tp1
, typename _Deleter
>
665 reset(_Tp1
* __p
, _Deleter __d
)
666 { __shared_ptr(__p
, __d
).swap(*this); }
668 // Allow class instantiation when _Tp is [cv-qual] void.
669 typename
std::tr1::add_reference
<_Tp
>::type
670 operator*() const // never throws
672 _GLIBCXX_DEBUG_ASSERT(_M_ptr
!= 0);
677 operator->() const // never throws
679 _GLIBCXX_DEBUG_ASSERT(_M_ptr
!= 0);
684 get() const // never throws
687 // Implicit conversion to "bool"
689 typedef _Tp
* __shared_ptr::*__unspecified_bool_type
;
692 operator __unspecified_bool_type() const // never throws
693 { return _M_ptr
== 0 ? 0 : &__shared_ptr::_M_ptr
; }
696 unique() const // never throws
697 { return _M_refcount
._M_unique(); }
700 use_count() const // never throws
701 { return _M_refcount
._M_get_use_count(); }
704 swap(__shared_ptr
<_Tp
, _Lp
>& __other
) // never throws
706 std::swap(_M_ptr
, __other
._M_ptr
);
707 _M_refcount
._M_swap(__other
._M_refcount
);
712 _M_get_deleter(const std::type_info
& __ti
) const
713 { return _M_refcount
._M_get_deleter(__ti
); }
715 template<typename _Tp1
, _Lock_policy _Lp1
>
717 _M_less(const __shared_ptr
<_Tp1
, _Lp1
>& __rhs
) const
718 { return _M_refcount
< __rhs
._M_refcount
; }
720 template<typename _Tp1
, _Lock_policy _Lp1
> friend class __shared_ptr
;
721 template<typename _Tp1
, _Lock_policy _Lp1
> friend class __weak_ptr
;
723 template<typename _Del
, typename _Tp1
, _Lock_policy _Lp1
>
724 friend _Del
* get_deleter(const __shared_ptr
<_Tp1
, _Lp1
>&);
726 // Friends injected into enclosing namespace and found by ADL:
727 template<typename _Tp1
>
729 operator==(const __shared_ptr
& __a
, const __shared_ptr
<_Tp1
, _Lp
>& __b
)
730 { return __a
.get() == __b
.get(); }
732 template<typename _Tp1
>
734 operator!=(const __shared_ptr
& __a
, const __shared_ptr
<_Tp1
, _Lp
>& __b
)
735 { return __a
.get() != __b
.get(); }
737 template<typename _Tp1
>
739 operator<(const __shared_ptr
& __a
, const __shared_ptr
<_Tp1
, _Lp
>& __b
)
740 { return __a
._M_less(__b
); }
742 _Tp
* _M_ptr
; // Contained pointer.
743 __shared_count
<_Lp
> _M_refcount
; // Reference counter.
746 // 2.2.3.8 shared_ptr specialized algorithms.
747 template<typename _Tp
, _Lock_policy _Lp
>
749 swap(__shared_ptr
<_Tp
, _Lp
>& __a
, __shared_ptr
<_Tp
, _Lp
>& __b
)
752 // 2.2.3.9 shared_ptr casts
753 /* The seemingly equivalent
754 * shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))
755 * will eventually result in undefined behaviour,
756 * attempting to delete the same object twice.
758 template<typename _Tp
, typename _Tp1
, _Lock_policy _Lp
>
759 inline __shared_ptr
<_Tp
, _Lp
>
760 static_pointer_cast(const __shared_ptr
<_Tp1
, _Lp
>& __r
)
761 { return __shared_ptr
<_Tp
, _Lp
>(__r
, __static_cast_tag()); }
763 /* The seemingly equivalent
764 * shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
765 * will eventually result in undefined behaviour,
766 * attempting to delete the same object twice.
768 template<typename _Tp
, typename _Tp1
, _Lock_policy _Lp
>
769 inline __shared_ptr
<_Tp
, _Lp
>
770 const_pointer_cast(const __shared_ptr
<_Tp1
, _Lp
>& __r
)
771 { return __shared_ptr
<_Tp
, _Lp
>(__r
, __const_cast_tag()); }
773 /* The seemingly equivalent
774 * shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
775 * will eventually result in undefined behaviour,
776 * attempting to delete the same object twice.
778 template<typename _Tp
, typename _Tp1
, _Lock_policy _Lp
>
779 inline __shared_ptr
<_Tp
, _Lp
>
780 dynamic_pointer_cast(const __shared_ptr
<_Tp1
, _Lp
>& __r
)
781 { return __shared_ptr
<_Tp
, _Lp
>(__r
, __dynamic_cast_tag()); }
783 // 2.2.3.7 shared_ptr I/O
784 template<typename _Ch
, typename _Tr
, typename _Tp
, _Lock_policy _Lp
>
785 std::basic_ostream
<_Ch
, _Tr
>&
786 operator<<(std::basic_ostream
<_Ch
, _Tr
>& __os
,
787 const __shared_ptr
<_Tp
, _Lp
>& __p
)
793 // 2.2.3.10 shared_ptr get_deleter (experimental)
794 template<typename _Del
, typename _Tp
, _Lock_policy _Lp
>
796 get_deleter(const __shared_ptr
<_Tp
, _Lp
>& __p
)
799 return static_cast<_Del
*>(__p
._M_get_deleter(typeid(_Del
)));
806 template<typename _Tp
, _Lock_policy _Lp
>
810 typedef _Tp element_type
;
813 : _M_ptr(0), _M_refcount() // never throws
816 // Generated copy constructor, assignment, destructor are fine.
818 // The "obvious" converting constructor implementation:
820 // template<typename _Tp1>
821 // __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
822 // : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
825 // has a serious problem.
827 // __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr)
828 // conversion may require access to *__r._M_ptr (virtual inheritance).
830 // It is not possible to avoid spurious access violations since
831 // in multithreaded programs __r._M_ptr may be invalidated at any point.
832 template<typename _Tp1
>
833 __weak_ptr(const __weak_ptr
<_Tp1
, _Lp
>& __r
)
834 : _M_refcount(__r
._M_refcount
) // never throws
836 __glibcxx_function_requires(_ConvertibleConcept
<_Tp1
*, _Tp
*>)
837 _M_ptr
= __r
.lock().get();
840 template<typename _Tp1
>
841 __weak_ptr(const __shared_ptr
<_Tp1
, _Lp
>& __r
)
842 : _M_ptr(__r
._M_ptr
), _M_refcount(__r
._M_refcount
) // never throws
843 { __glibcxx_function_requires(_ConvertibleConcept
<_Tp1
*, _Tp
*>) }
845 template<typename _Tp1
>
847 operator=(const __weak_ptr
<_Tp1
, _Lp
>& __r
) // never throws
849 _M_ptr
= __r
.lock().get();
850 _M_refcount
= __r
._M_refcount
;
854 template<typename _Tp1
>
856 operator=(const __shared_ptr
<_Tp1
, _Lp
>& __r
) // never throws
859 _M_refcount
= __r
._M_refcount
;
863 __shared_ptr
<_Tp
, _Lp
>
864 lock() const // never throws
867 // Optimization: avoid throw overhead.
869 return __shared_ptr
<element_type
, _Lp
>();
873 return __shared_ptr
<element_type
, _Lp
>(*this);
875 __catch(const bad_weak_ptr
&)
877 // Q: How can we get here?
878 // A: Another thread may have invalidated r after the
879 // use_count test above.
880 return __shared_ptr
<element_type
, _Lp
>();
884 // Optimization: avoid try/catch overhead when single threaded.
885 return expired() ? __shared_ptr
<element_type
, _Lp
>()
886 : __shared_ptr
<element_type
, _Lp
>(*this);
892 use_count() const // never throws
893 { return _M_refcount
._M_get_use_count(); }
896 expired() const // never throws
897 { return _M_refcount
._M_get_use_count() == 0; }
900 reset() // never throws
901 { __weak_ptr().swap(*this); }
904 swap(__weak_ptr
& __s
) // never throws
906 std::swap(_M_ptr
, __s
._M_ptr
);
907 _M_refcount
._M_swap(__s
._M_refcount
);
911 // Used by __enable_shared_from_this.
913 _M_assign(_Tp
* __ptr
, const __shared_count
<_Lp
>& __refcount
)
916 _M_refcount
= __refcount
;
919 template<typename _Tp1
>
921 _M_less(const __weak_ptr
<_Tp1
, _Lp
>& __rhs
) const
922 { return _M_refcount
< __rhs
._M_refcount
; }
924 template<typename _Tp1
, _Lock_policy _Lp1
> friend class __shared_ptr
;
925 template<typename _Tp1
, _Lock_policy _Lp1
> friend class __weak_ptr
;
926 friend class __enable_shared_from_this
<_Tp
, _Lp
>;
927 friend class enable_shared_from_this
<_Tp
>;
929 // Friend injected into namespace and found by ADL.
930 template<typename _Tp1
>
932 operator<(const __weak_ptr
& __lhs
, const __weak_ptr
<_Tp1
, _Lp
>& __rhs
)
933 { return __lhs
._M_less(__rhs
); }
935 _Tp
* _M_ptr
; // Contained pointer.
936 __weak_count
<_Lp
> _M_refcount
; // Reference counter.
939 // 2.2.4.7 weak_ptr specialized algorithms.
940 template<typename _Tp
, _Lock_policy _Lp
>
942 swap(__weak_ptr
<_Tp
, _Lp
>& __a
, __weak_ptr
<_Tp
, _Lp
>& __b
)
946 template<typename _Tp
, _Lock_policy _Lp
>
947 class __enable_shared_from_this
950 __enable_shared_from_this() { }
952 __enable_shared_from_this(const __enable_shared_from_this
&) { }
954 __enable_shared_from_this
&
955 operator=(const __enable_shared_from_this
&)
958 ~__enable_shared_from_this() { }
961 __shared_ptr
<_Tp
, _Lp
>
963 { return __shared_ptr
<_Tp
, _Lp
>(this->_M_weak_this
); }
965 __shared_ptr
<const _Tp
, _Lp
>
966 shared_from_this() const
967 { return __shared_ptr
<const _Tp
, _Lp
>(this->_M_weak_this
); }
970 template<typename _Tp1
>
972 _M_weak_assign(_Tp1
* __p
, const __shared_count
<_Lp
>& __n
) const
973 { _M_weak_this
._M_assign(__p
, __n
); }
975 template<typename _Tp1
>
977 __enable_shared_from_this_helper(const __shared_count
<_Lp
>& __pn
,
978 const __enable_shared_from_this
* __pe
,
982 __pe
->_M_weak_assign(const_cast<_Tp1
*>(__px
), __pn
);
985 mutable __weak_ptr
<_Tp
, _Lp
> _M_weak_this
;
989 // The actual shared_ptr, with forwarding constructors and
990 // assignment operators.
991 template<typename _Tp
>
993 : public __shared_ptr
<_Tp
>
997 : __shared_ptr
<_Tp
>() { }
999 template<typename _Tp1
>
1001 shared_ptr(_Tp1
* __p
)
1002 : __shared_ptr
<_Tp
>(__p
) { }
1004 template<typename _Tp1
, typename _Deleter
>
1005 shared_ptr(_Tp1
* __p
, _Deleter __d
)
1006 : __shared_ptr
<_Tp
>(__p
, __d
) { }
1008 template<typename _Tp1
>
1009 shared_ptr(const shared_ptr
<_Tp1
>& __r
)
1010 : __shared_ptr
<_Tp
>(__r
) { }
1012 template<typename _Tp1
>
1014 shared_ptr(const weak_ptr
<_Tp1
>& __r
)
1015 : __shared_ptr
<_Tp
>(__r
) { }
1017 #if !defined(__GXX_EXPERIMENTAL_CXX0X__) || _GLIBCXX_USE_DEPRECATED
1018 template<typename _Tp1
>
1020 shared_ptr(std::auto_ptr
<_Tp1
>& __r
)
1021 : __shared_ptr
<_Tp
>(__r
) { }
1024 template<typename _Tp1
>
1025 shared_ptr(const shared_ptr
<_Tp1
>& __r
, __static_cast_tag
)
1026 : __shared_ptr
<_Tp
>(__r
, __static_cast_tag()) { }
1028 template<typename _Tp1
>
1029 shared_ptr(const shared_ptr
<_Tp1
>& __r
, __const_cast_tag
)
1030 : __shared_ptr
<_Tp
>(__r
, __const_cast_tag()) { }
1032 template<typename _Tp1
>
1033 shared_ptr(const shared_ptr
<_Tp1
>& __r
, __dynamic_cast_tag
)
1034 : __shared_ptr
<_Tp
>(__r
, __dynamic_cast_tag()) { }
1036 template<typename _Tp1
>
1038 operator=(const shared_ptr
<_Tp1
>& __r
) // never throws
1040 this->__shared_ptr
<_Tp
>::operator=(__r
);
1044 #if !defined(__GXX_EXPERIMENTAL_CXX0X__) || _GLIBCXX_USE_DEPRECATED
1045 template<typename _Tp1
>
1047 operator=(std::auto_ptr
<_Tp1
>& __r
)
1049 this->__shared_ptr
<_Tp
>::operator=(__r
);
1055 // 2.2.3.8 shared_ptr specialized algorithms.
1056 template<typename _Tp
>
1058 swap(__shared_ptr
<_Tp
>& __a
, __shared_ptr
<_Tp
>& __b
)
1061 template<typename _Tp
, typename _Tp1
>
1062 inline shared_ptr
<_Tp
>
1063 static_pointer_cast(const shared_ptr
<_Tp1
>& __r
)
1064 { return shared_ptr
<_Tp
>(__r
, __static_cast_tag()); }
1066 template<typename _Tp
, typename _Tp1
>
1067 inline shared_ptr
<_Tp
>
1068 const_pointer_cast(const shared_ptr
<_Tp1
>& __r
)
1069 { return shared_ptr
<_Tp
>(__r
, __const_cast_tag()); }
1071 template<typename _Tp
, typename _Tp1
>
1072 inline shared_ptr
<_Tp
>
1073 dynamic_pointer_cast(const shared_ptr
<_Tp1
>& __r
)
1074 { return shared_ptr
<_Tp
>(__r
, __dynamic_cast_tag()); }
1077 // The actual weak_ptr, with forwarding constructors and
1078 // assignment operators.
1079 template<typename _Tp
>
1081 : public __weak_ptr
<_Tp
>
1085 : __weak_ptr
<_Tp
>() { }
1087 template<typename _Tp1
>
1088 weak_ptr(const weak_ptr
<_Tp1
>& __r
)
1089 : __weak_ptr
<_Tp
>(__r
) { }
1091 template<typename _Tp1
>
1092 weak_ptr(const shared_ptr
<_Tp1
>& __r
)
1093 : __weak_ptr
<_Tp
>(__r
) { }
1095 template<typename _Tp1
>
1097 operator=(const weak_ptr
<_Tp1
>& __r
) // never throws
1099 this->__weak_ptr
<_Tp
>::operator=(__r
);
1103 template<typename _Tp1
>
1105 operator=(const shared_ptr
<_Tp1
>& __r
) // never throws
1107 this->__weak_ptr
<_Tp
>::operator=(__r
);
1112 lock() const // never throws
1115 if (this->expired())
1116 return shared_ptr
<_Tp
>();
1120 return shared_ptr
<_Tp
>(*this);
1122 __catch(const bad_weak_ptr
&)
1124 return shared_ptr
<_Tp
>();
1127 return this->expired() ? shared_ptr
<_Tp
>()
1128 : shared_ptr
<_Tp
>(*this);
1133 template<typename _Tp
>
1134 class enable_shared_from_this
1137 enable_shared_from_this() { }
1139 enable_shared_from_this(const enable_shared_from_this
&) { }
1141 enable_shared_from_this
&
1142 operator=(const enable_shared_from_this
&)
1145 ~enable_shared_from_this() { }
1150 { return shared_ptr
<_Tp
>(this->_M_weak_this
); }
1152 shared_ptr
<const _Tp
>
1153 shared_from_this() const
1154 { return shared_ptr
<const _Tp
>(this->_M_weak_this
); }
1157 template<typename _Tp1
>
1159 _M_weak_assign(_Tp1
* __p
, const __shared_count
<>& __n
) const
1160 { _M_weak_this
._M_assign(__p
, __n
); }
1162 template<typename _Tp1
>
1164 __enable_shared_from_this_helper(const __shared_count
<>& __pn
,
1165 const enable_shared_from_this
* __pe
,
1169 __pe
->_M_weak_assign(const_cast<_Tp1
*>(__px
), __pn
);
1172 mutable weak_ptr
<_Tp
> _M_weak_this
;
1175 _GLIBCXX_END_NAMESPACE_VERSION
1179 #endif // _TR1_SHARED_PTR_H