kmalloc: Avoid code duplication.
[dragonfly.git] / contrib / gcc-4.7 / libstdc++-v3 / include / tr1 / shared_ptr.h
blob5a1eb038a38b593a9d4b1c615cb1230834e875d2
1 // <tr1/shared_ptr.h> -*- C++ -*-
3 // Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc.
5 //
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)
10 // any later version.
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/>.
26 // shared_count.hpp
27 // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29 // shared_ptr.hpp
30 // Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
31 // Copyright (C) 2001, 2002, 2003 Peter Dimov
33 // weak_ptr.hpp
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)
55 namespace tr1
57 _GLIBCXX_BEGIN_NAMESPACE_VERSION
59 /**
60 * @brief Exception possibly thrown by @c shared_ptr.
61 * @ingroup exceptions
63 class bad_weak_ptr : public std::exception
65 public:
66 virtual char const*
67 what() const throw()
68 { return "tr1::bad_weak_ptr"; }
71 // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
72 inline void
73 __throw_bad_weak_ptr()
75 #if __EXCEPTIONS
76 throw bad_weak_ptr();
77 #else
78 __builtin_abort();
79 #endif
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>
90 class _Mutex_base
92 protected:
93 // The atomic policy uses fully-fenced builtins, single doesn't care.
94 enum { _S_need_barriers = 0 };
97 template<>
98 class _Mutex_base<_S_mutex>
99 : public __gnu_cxx::__mutex
101 protected:
102 // This policy is used when atomic builtins are not available.
103 // The replacement atomic operations might not have the necessary
104 // memory barriers.
105 enum { _S_need_barriers = 1 };
108 template<_Lock_policy _Lp = __default_lock_policy>
109 class _Sp_counted_base
110 : public _Mutex_base<_Lp>
112 public:
113 _Sp_counted_base()
114 : _M_use_count(1), _M_weak_count(1) { }
116 virtual
117 ~_Sp_counted_base() // nothrow
120 // Called when _M_use_count drops to zero, to release the resources
121 // managed by *this.
122 virtual void
123 _M_dispose() = 0; // nothrow
125 // Called when _M_weak_count drops to zero.
126 virtual void
127 _M_destroy() // nothrow
128 { delete this; }
130 virtual void*
131 _M_get_deleter(const std::type_info&) = 0;
133 void
134 _M_add_ref_copy()
135 { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
137 void
138 _M_add_ref_lock();
140 void
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);
148 _M_dispose();
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,
162 -1) == 1)
164 _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
165 _M_destroy();
170 void
171 _M_weak_add_ref() // nothrow
172 { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
174 void
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)
184 // See _M_release(),
185 // destroy() must observe results of dispose()
186 _GLIBCXX_READ_MEM_BARRIER;
187 _GLIBCXX_WRITE_MEM_BARRIER;
189 _M_destroy();
193 long
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);
201 private:
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)
209 template<>
210 inline void
211 _Sp_counted_base<_S_single>::
212 _M_add_ref_lock()
214 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
216 _M_use_count = 0;
217 __throw_bad_weak_ptr();
221 template<>
222 inline void
223 _Sp_counted_base<_S_mutex>::
224 _M_add_ref_lock()
226 __gnu_cxx::__scoped_lock sentry(*this);
227 if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
229 _M_use_count = 0;
230 __throw_bad_weak_ptr();
234 template<>
235 inline void
236 _Sp_counted_base<_S_atomic>::
237 _M_add_ref_lock()
239 // Perform lock-free add-if-not-zero operation.
240 _Atomic_word __count = _M_use_count;
243 if (__count == 0)
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,
250 __ATOMIC_RELAXED));
253 template<typename _Ptr, typename _Deleter, _Lock_policy _Lp>
254 class _Sp_counted_base_impl
255 : public _Sp_counted_base<_Lp>
257 public:
258 // Precondition: __d(__p) must not throw.
259 _Sp_counted_base_impl(_Ptr __p, _Deleter __d)
260 : _M_ptr(__p), _M_del(__d) { }
262 virtual void
263 _M_dispose() // nothrow
264 { _M_del(_M_ptr); }
266 virtual void*
267 _M_get_deleter(const std::type_info& __ti)
269 #ifdef __GXX_RTTI
270 return __ti == typeid(_Deleter) ? &_M_del : 0;
271 #else
272 return 0;
273 #endif
276 private:
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>
285 class __weak_count;
287 template<typename _Tp>
288 struct _Sp_deleter
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>
296 class __shared_count
298 public:
299 __shared_count()
300 : _M_pi(0) // nothrow
303 template<typename _Ptr>
304 __shared_count(_Ptr __p) : _M_pi(0)
306 __try
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>());
312 __catch(...)
314 delete __p;
315 __throw_exception_again;
319 template<typename _Ptr, typename _Deleter>
320 __shared_count(_Ptr __p, _Deleter __d) : _M_pi(0)
322 __try
324 _M_pi = new _Sp_counted_base_impl<_Ptr, _Deleter, _Lp>(__p, __d);
326 __catch(...)
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>
335 explicit
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>()))
339 { __r.release(); }
341 // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
342 explicit
343 __shared_count(const __weak_count<_Lp>& __r);
345 ~__shared_count() // nothrow
347 if (_M_pi != 0)
348 _M_pi->_M_release();
351 __shared_count(const __shared_count& __r)
352 : _M_pi(__r._M_pi) // nothrow
354 if (_M_pi != 0)
355 _M_pi->_M_add_ref_copy();
358 __shared_count&
359 operator=(const __shared_count& __r) // nothrow
361 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
362 if (__tmp != _M_pi)
364 if (__tmp != 0)
365 __tmp->_M_add_ref_copy();
366 if (_M_pi != 0)
367 _M_pi->_M_release();
368 _M_pi = __tmp;
370 return *this;
373 void
374 _M_swap(__shared_count& __r) // nothrow
376 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
377 __r._M_pi = _M_pi;
378 _M_pi = __tmp;
381 long
382 _M_get_use_count() const // nothrow
383 { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
385 bool
386 _M_unique() const // nothrow
387 { return this->_M_get_use_count() == 1; }
389 friend inline bool
390 operator==(const __shared_count& __a, const __shared_count& __b)
391 { return __a._M_pi == __b._M_pi; }
393 friend inline bool
394 operator<(const __shared_count& __a, const __shared_count& __b)
395 { return std::less<_Sp_counted_base<_Lp>*>()(__a._M_pi, __b._M_pi); }
397 void*
398 _M_get_deleter(const std::type_info& __ti) const
399 { return _M_pi ? _M_pi->_M_get_deleter(__ti) : 0; }
401 private:
402 friend class __weak_count<_Lp>;
404 _Sp_counted_base<_Lp>* _M_pi;
408 template<_Lock_policy _Lp>
409 class __weak_count
411 public:
412 __weak_count()
413 : _M_pi(0) // nothrow
416 __weak_count(const __shared_count<_Lp>& __r)
417 : _M_pi(__r._M_pi) // nothrow
419 if (_M_pi != 0)
420 _M_pi->_M_weak_add_ref();
423 __weak_count(const __weak_count<_Lp>& __r)
424 : _M_pi(__r._M_pi) // nothrow
426 if (_M_pi != 0)
427 _M_pi->_M_weak_add_ref();
430 ~__weak_count() // nothrow
432 if (_M_pi != 0)
433 _M_pi->_M_weak_release();
436 __weak_count<_Lp>&
437 operator=(const __shared_count<_Lp>& __r) // nothrow
439 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
440 if (__tmp != 0)
441 __tmp->_M_weak_add_ref();
442 if (_M_pi != 0)
443 _M_pi->_M_weak_release();
444 _M_pi = __tmp;
445 return *this;
448 __weak_count<_Lp>&
449 operator=(const __weak_count<_Lp>& __r) // nothrow
451 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
452 if (__tmp != 0)
453 __tmp->_M_weak_add_ref();
454 if (_M_pi != 0)
455 _M_pi->_M_weak_release();
456 _M_pi = __tmp;
457 return *this;
460 void
461 _M_swap(__weak_count<_Lp>& __r) // nothrow
463 _Sp_counted_base<_Lp>* __tmp = __r._M_pi;
464 __r._M_pi = _M_pi;
465 _M_pi = __tmp;
468 long
469 _M_get_use_count() const // nothrow
470 { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
472 friend inline bool
473 operator==(const __weak_count<_Lp>& __a, const __weak_count<_Lp>& __b)
474 { return __a._M_pi == __b._M_pi; }
476 friend inline bool
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); }
480 private:
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>
488 inline
489 __shared_count<_Lp>::
490 __shared_count(const __weak_count<_Lp>& __r)
491 : _M_pi(__r._M_pi)
493 if (_M_pi != 0)
494 _M_pi->_M_add_ref_lock();
495 else
496 __throw_bad_weak_ptr();
499 // Forward declarations.
500 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
501 class __shared_ptr;
503 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
504 class __weak_ptr;
506 template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
507 class __enable_shared_from_this;
509 template<typename _Tp>
510 class shared_ptr;
512 template<typename _Tp>
513 class weak_ptr;
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>
522 void
523 __enable_shared_from_this_helper(const __shared_count<_Lp>&,
524 const __enable_shared_from_this<_Tp1,
525 _Lp>*, const _Tp2*);
527 // Friend of enable_shared_from_this.
528 template<typename _Tp1, typename _Tp2>
529 void
530 __enable_shared_from_this_helper(const __shared_count<>&,
531 const enable_shared_from_this<_Tp1>*,
532 const _Tp2*);
534 template<_Lock_policy _Lp>
535 inline void
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>
548 class __shared_ptr
550 public:
551 typedef _Tp element_type;
553 __shared_ptr()
554 : _M_ptr(0), _M_refcount() // never throws
557 template<typename _Tp1>
558 explicit
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>
584 explicit
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)
590 // did not throw.
591 _M_ptr = __r._M_ptr;
594 #if !defined(__GXX_EXPERIMENTAL_CXX0X__) || _GLIBCXX_USE_DEPRECATED
595 // Postcondition: use_count() == 1 and __r.get() == 0
596 template<typename _Tp1>
597 explicit
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);
608 #endif
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>
632 __shared_ptr&
633 operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws
635 _M_ptr = __r._M_ptr;
636 _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
637 return *this;
640 #if !defined(__GXX_EXPERIMENTAL_CXX0X__) || _GLIBCXX_USE_DEPRECATED
641 template<typename _Tp1>
642 __shared_ptr&
643 operator=(std::auto_ptr<_Tp1>& __r)
645 __shared_ptr(__r).swap(*this);
646 return *this;
648 #endif
650 void
651 reset() // never throws
652 { __shared_ptr().swap(*this); }
654 template<typename _Tp1>
655 void
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>
664 void
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);
673 return *_M_ptr;
676 _Tp*
677 operator->() const // never throws
679 _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
680 return _M_ptr;
683 _Tp*
684 get() const // never throws
685 { return _M_ptr; }
687 // Implicit conversion to "bool"
688 private:
689 typedef _Tp* __shared_ptr::*__unspecified_bool_type;
691 public:
692 operator __unspecified_bool_type() const // never throws
693 { return _M_ptr == 0 ? 0 : &__shared_ptr::_M_ptr; }
695 bool
696 unique() const // never throws
697 { return _M_refcount._M_unique(); }
699 long
700 use_count() const // never throws
701 { return _M_refcount._M_get_use_count(); }
703 void
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);
710 private:
711 void*
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>
716 bool
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>
728 friend inline bool
729 operator==(const __shared_ptr& __a, const __shared_ptr<_Tp1, _Lp>& __b)
730 { return __a.get() == __b.get(); }
732 template<typename _Tp1>
733 friend inline bool
734 operator!=(const __shared_ptr& __a, const __shared_ptr<_Tp1, _Lp>& __b)
735 { return __a.get() != __b.get(); }
737 template<typename _Tp1>
738 friend inline bool
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>
748 inline void
749 swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b)
750 { __a.swap(__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)
789 __os << __p.get();
790 return __os;
793 // 2.2.3.10 shared_ptr get_deleter (experimental)
794 template<typename _Del, typename _Tp, _Lock_policy _Lp>
795 inline _Del*
796 get_deleter(const __shared_ptr<_Tp, _Lp>& __p)
798 #ifdef __GXX_RTTI
799 return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
800 #else
801 return 0;
802 #endif
806 template<typename _Tp, _Lock_policy _Lp>
807 class __weak_ptr
809 public:
810 typedef _Tp element_type;
812 __weak_ptr()
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
823 // { }
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>
846 __weak_ptr&
847 operator=(const __weak_ptr<_Tp1, _Lp>& __r) // never throws
849 _M_ptr = __r.lock().get();
850 _M_refcount = __r._M_refcount;
851 return *this;
854 template<typename _Tp1>
855 __weak_ptr&
856 operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws
858 _M_ptr = __r._M_ptr;
859 _M_refcount = __r._M_refcount;
860 return *this;
863 __shared_ptr<_Tp, _Lp>
864 lock() const // never throws
866 #ifdef __GTHREADS
867 // Optimization: avoid throw overhead.
868 if (expired())
869 return __shared_ptr<element_type, _Lp>();
871 __try
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>();
883 #else
884 // Optimization: avoid try/catch overhead when single threaded.
885 return expired() ? __shared_ptr<element_type, _Lp>()
886 : __shared_ptr<element_type, _Lp>(*this);
888 #endif
889 } // XXX MT
891 long
892 use_count() const // never throws
893 { return _M_refcount._M_get_use_count(); }
895 bool
896 expired() const // never throws
897 { return _M_refcount._M_get_use_count() == 0; }
899 void
900 reset() // never throws
901 { __weak_ptr().swap(*this); }
903 void
904 swap(__weak_ptr& __s) // never throws
906 std::swap(_M_ptr, __s._M_ptr);
907 _M_refcount._M_swap(__s._M_refcount);
910 private:
911 // Used by __enable_shared_from_this.
912 void
913 _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount)
915 _M_ptr = __ptr;
916 _M_refcount = __refcount;
919 template<typename _Tp1>
920 bool
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>
931 friend inline bool
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>
941 inline void
942 swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b)
943 { __a.swap(__b); }
946 template<typename _Tp, _Lock_policy _Lp>
947 class __enable_shared_from_this
949 protected:
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&)
956 { return *this; }
958 ~__enable_shared_from_this() { }
960 public:
961 __shared_ptr<_Tp, _Lp>
962 shared_from_this()
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); }
969 private:
970 template<typename _Tp1>
971 void
972 _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const
973 { _M_weak_this._M_assign(__p, __n); }
975 template<typename _Tp1>
976 friend void
977 __enable_shared_from_this_helper(const __shared_count<_Lp>& __pn,
978 const __enable_shared_from_this* __pe,
979 const _Tp1* __px)
981 if (__pe != 0)
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>
992 class shared_ptr
993 : public __shared_ptr<_Tp>
995 public:
996 shared_ptr()
997 : __shared_ptr<_Tp>() { }
999 template<typename _Tp1>
1000 explicit
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>
1013 explicit
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>
1019 explicit
1020 shared_ptr(std::auto_ptr<_Tp1>& __r)
1021 : __shared_ptr<_Tp>(__r) { }
1022 #endif
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>
1037 shared_ptr&
1038 operator=(const shared_ptr<_Tp1>& __r) // never throws
1040 this->__shared_ptr<_Tp>::operator=(__r);
1041 return *this;
1044 #if !defined(__GXX_EXPERIMENTAL_CXX0X__) || _GLIBCXX_USE_DEPRECATED
1045 template<typename _Tp1>
1046 shared_ptr&
1047 operator=(std::auto_ptr<_Tp1>& __r)
1049 this->__shared_ptr<_Tp>::operator=(__r);
1050 return *this;
1052 #endif
1055 // 2.2.3.8 shared_ptr specialized algorithms.
1056 template<typename _Tp>
1057 inline void
1058 swap(__shared_ptr<_Tp>& __a, __shared_ptr<_Tp>& __b)
1059 { __a.swap(__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>
1080 class weak_ptr
1081 : public __weak_ptr<_Tp>
1083 public:
1084 weak_ptr()
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>
1096 weak_ptr&
1097 operator=(const weak_ptr<_Tp1>& __r) // never throws
1099 this->__weak_ptr<_Tp>::operator=(__r);
1100 return *this;
1103 template<typename _Tp1>
1104 weak_ptr&
1105 operator=(const shared_ptr<_Tp1>& __r) // never throws
1107 this->__weak_ptr<_Tp>::operator=(__r);
1108 return *this;
1111 shared_ptr<_Tp>
1112 lock() const // never throws
1114 #ifdef __GTHREADS
1115 if (this->expired())
1116 return shared_ptr<_Tp>();
1118 __try
1120 return shared_ptr<_Tp>(*this);
1122 __catch(const bad_weak_ptr&)
1124 return shared_ptr<_Tp>();
1126 #else
1127 return this->expired() ? shared_ptr<_Tp>()
1128 : shared_ptr<_Tp>(*this);
1129 #endif
1133 template<typename _Tp>
1134 class enable_shared_from_this
1136 protected:
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&)
1143 { return *this; }
1145 ~enable_shared_from_this() { }
1147 public:
1148 shared_ptr<_Tp>
1149 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); }
1156 private:
1157 template<typename _Tp1>
1158 void
1159 _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const
1160 { _M_weak_this._M_assign(__p, __n); }
1162 template<typename _Tp1>
1163 friend void
1164 __enable_shared_from_this_helper(const __shared_count<>& __pn,
1165 const enable_shared_from_this* __pe,
1166 const _Tp1* __px)
1168 if (__pe != 0)
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