1f8a1b7d9SAlexander Kabaev // <tr1/boost_shared_ptr.h> -*- C++ -*-
2f8a1b7d9SAlexander Kabaev 
3f8a1b7d9SAlexander Kabaev // Copyright (C) 2005, 2006 Free Software Foundation, Inc.
4f8a1b7d9SAlexander Kabaev //
5f8a1b7d9SAlexander Kabaev // This file is part of the GNU ISO C++ Library.  This library is free
6f8a1b7d9SAlexander Kabaev // software; you can redistribute it and/or modify it under the
7f8a1b7d9SAlexander Kabaev // terms of the GNU General Public License as published by the
8f8a1b7d9SAlexander Kabaev // Free Software Foundation; either version 2, or (at your option)
9f8a1b7d9SAlexander Kabaev // any later version.
10f8a1b7d9SAlexander Kabaev 
11f8a1b7d9SAlexander Kabaev // This library is distributed in the hope that it will be useful,
12f8a1b7d9SAlexander Kabaev // but WITHOUT ANY WARRANTY; without even the implied warranty of
13f8a1b7d9SAlexander Kabaev // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14f8a1b7d9SAlexander Kabaev // GNU General Public License for more details.
15f8a1b7d9SAlexander Kabaev 
16f8a1b7d9SAlexander Kabaev // You should have received a copy of the GNU General Public License along
17f8a1b7d9SAlexander Kabaev // with this library; see the file COPYING.  If not, write to the Free
18f8a1b7d9SAlexander Kabaev // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19f8a1b7d9SAlexander Kabaev // USA.
20f8a1b7d9SAlexander Kabaev 
21f8a1b7d9SAlexander Kabaev // As a special exception, you may use this file as part of a free software
22f8a1b7d9SAlexander Kabaev // library without restriction.  Specifically, if other files instantiate
23f8a1b7d9SAlexander Kabaev // templates or use macros or inline functions from this file, or you compile
24f8a1b7d9SAlexander Kabaev // this file and link it with other files to produce an executable, this
25f8a1b7d9SAlexander Kabaev // file does not by itself cause the resulting executable to be covered by
26f8a1b7d9SAlexander Kabaev // the GNU General Public License.  This exception does not however
27f8a1b7d9SAlexander Kabaev // invalidate any other reasons why the executable file might be covered by
28f8a1b7d9SAlexander Kabaev // the GNU General Public License.
29f8a1b7d9SAlexander Kabaev 
30f8a1b7d9SAlexander Kabaev //  shared_count.hpp
31f8a1b7d9SAlexander Kabaev //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
32f8a1b7d9SAlexander Kabaev 
33f8a1b7d9SAlexander Kabaev //  shared_ptr.hpp
34f8a1b7d9SAlexander Kabaev //  Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
35f8a1b7d9SAlexander Kabaev //  Copyright (C) 2001, 2002, 2003 Peter Dimov
36f8a1b7d9SAlexander Kabaev 
37f8a1b7d9SAlexander Kabaev //  weak_ptr.hpp
38f8a1b7d9SAlexander Kabaev //  Copyright (C) 2001, 2002, 2003 Peter Dimov
39f8a1b7d9SAlexander Kabaev 
40f8a1b7d9SAlexander Kabaev //  enable_shared_from_this.hpp
41f8a1b7d9SAlexander Kabaev //  Copyright (C) 2002 Peter Dimov
42f8a1b7d9SAlexander Kabaev 
43f8a1b7d9SAlexander Kabaev // Distributed under the Boost Software License, Version 1.0. (See
44f8a1b7d9SAlexander Kabaev // accompanying file LICENSE_1_0.txt or copy at
45f8a1b7d9SAlexander Kabaev // http://www.boost.org/LICENSE_1_0.txt)
46f8a1b7d9SAlexander Kabaev 
47f8a1b7d9SAlexander Kabaev // GCC Note:  based on version 1.32.0 of the Boost library.
48f8a1b7d9SAlexander Kabaev 
49f8a1b7d9SAlexander Kabaev /** @file tr1/boost_shared_ptr.h
50f8a1b7d9SAlexander Kabaev  *  This is an internal header file, included by other library headers.
51f8a1b7d9SAlexander Kabaev  *  You should not attempt to use it directly.
52f8a1b7d9SAlexander Kabaev  */
53f8a1b7d9SAlexander Kabaev 
54f8a1b7d9SAlexander Kabaev #ifndef _BOOST_SHARED_PTR_H
55f8a1b7d9SAlexander Kabaev #define _BOOST_SHARED_PTR_H 1
56f8a1b7d9SAlexander Kabaev 
57f8a1b7d9SAlexander Kabaev namespace std
58f8a1b7d9SAlexander Kabaev {
_GLIBCXX_BEGIN_NAMESPACE(tr1)59f8a1b7d9SAlexander Kabaev _GLIBCXX_BEGIN_NAMESPACE(tr1)
60f8a1b7d9SAlexander Kabaev 
61f8a1b7d9SAlexander Kabaev   class bad_weak_ptr : public std::exception
62f8a1b7d9SAlexander Kabaev   {
63f8a1b7d9SAlexander Kabaev   public:
64f8a1b7d9SAlexander Kabaev     virtual char const*
65f8a1b7d9SAlexander Kabaev     what() const throw()
66f8a1b7d9SAlexander Kabaev     { return "tr1::bad_weak_ptr"; }
67f8a1b7d9SAlexander Kabaev   };
68f8a1b7d9SAlexander Kabaev 
69f8a1b7d9SAlexander Kabaev   // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
70f8a1b7d9SAlexander Kabaev   inline void
__throw_bad_weak_ptr()71f8a1b7d9SAlexander Kabaev   __throw_bad_weak_ptr()
72f8a1b7d9SAlexander Kabaev   {
73f8a1b7d9SAlexander Kabaev #if __EXCEPTIONS
74f8a1b7d9SAlexander Kabaev     throw bad_weak_ptr();
75f8a1b7d9SAlexander Kabaev #else
76f8a1b7d9SAlexander Kabaev     std::abort();
77f8a1b7d9SAlexander Kabaev #endif
78f8a1b7d9SAlexander Kabaev   }
79f8a1b7d9SAlexander Kabaev 
80f8a1b7d9SAlexander Kabaev   using __gnu_cxx::_Lock_policy;
81f8a1b7d9SAlexander Kabaev   using __gnu_cxx::__default_lock_policy;
82f8a1b7d9SAlexander Kabaev   using __gnu_cxx::_S_single;
83f8a1b7d9SAlexander Kabaev   using __gnu_cxx::_S_mutex;
84f8a1b7d9SAlexander Kabaev   using __gnu_cxx::_S_atomic;
85f8a1b7d9SAlexander Kabaev 
86f8a1b7d9SAlexander Kabaev   template<typename _Tp>
87f8a1b7d9SAlexander Kabaev     struct _Sp_deleter
88f8a1b7d9SAlexander Kabaev     {
89f8a1b7d9SAlexander Kabaev       typedef void result_type;
90f8a1b7d9SAlexander Kabaev       typedef _Tp* argument_type;
91f8a1b7d9SAlexander Kabaev 
92f8a1b7d9SAlexander Kabaev       void
operator_Sp_deleter93f8a1b7d9SAlexander Kabaev       operator()(_Tp* __p) const
94f8a1b7d9SAlexander Kabaev       { delete __p; }
95f8a1b7d9SAlexander Kabaev     };
96f8a1b7d9SAlexander Kabaev 
97f8a1b7d9SAlexander Kabaev   // Empty helper class except when the template argument is _S_mutex.
98f8a1b7d9SAlexander Kabaev   template<_Lock_policy _Lp>
99f8a1b7d9SAlexander Kabaev     class _Mutex_base
100f8a1b7d9SAlexander Kabaev     { };
101f8a1b7d9SAlexander Kabaev 
102f8a1b7d9SAlexander Kabaev   template<>
103f8a1b7d9SAlexander Kabaev     class _Mutex_base<_S_mutex>
104f8a1b7d9SAlexander Kabaev     : public __gnu_cxx::__mutex
105f8a1b7d9SAlexander Kabaev     { };
106f8a1b7d9SAlexander Kabaev 
107f8a1b7d9SAlexander Kabaev   template<_Lock_policy _Lp = __default_lock_policy>
108f8a1b7d9SAlexander Kabaev     class _Sp_counted_base
109f8a1b7d9SAlexander Kabaev     : public _Mutex_base<_Lp>
110f8a1b7d9SAlexander Kabaev     {
111f8a1b7d9SAlexander Kabaev     public:
_Sp_counted_base()112f8a1b7d9SAlexander Kabaev       _Sp_counted_base()
113f8a1b7d9SAlexander Kabaev       : _M_use_count(1), _M_weak_count(1) { }
114f8a1b7d9SAlexander Kabaev 
115f8a1b7d9SAlexander Kabaev       virtual
~_Sp_counted_base()116f8a1b7d9SAlexander Kabaev       ~_Sp_counted_base() // nothrow
117f8a1b7d9SAlexander Kabaev       { }
118f8a1b7d9SAlexander Kabaev 
119f8a1b7d9SAlexander Kabaev       // Called when _M_use_count drops to zero, to release the resources
120f8a1b7d9SAlexander Kabaev       // managed by *this.
121f8a1b7d9SAlexander Kabaev       virtual void
122f8a1b7d9SAlexander Kabaev       _M_dispose() = 0; // nothrow
123f8a1b7d9SAlexander Kabaev 
124f8a1b7d9SAlexander Kabaev       // Called when _M_weak_count drops to zero.
125f8a1b7d9SAlexander Kabaev       virtual void
_M_destroy()126f8a1b7d9SAlexander Kabaev       _M_destroy() // nothrow
127f8a1b7d9SAlexander Kabaev       { delete this; }
128f8a1b7d9SAlexander Kabaev 
129f8a1b7d9SAlexander Kabaev       virtual void*
130f8a1b7d9SAlexander Kabaev       _M_get_deleter(const std::type_info&) = 0;
131f8a1b7d9SAlexander Kabaev 
132f8a1b7d9SAlexander Kabaev       void
_M_add_ref_copy()133f8a1b7d9SAlexander Kabaev       _M_add_ref_copy()
134f8a1b7d9SAlexander Kabaev       { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); }
135f8a1b7d9SAlexander Kabaev 
136f8a1b7d9SAlexander Kabaev       void
137f8a1b7d9SAlexander Kabaev       _M_add_ref_lock();
138f8a1b7d9SAlexander Kabaev 
139f8a1b7d9SAlexander Kabaev       void
_M_release()140f8a1b7d9SAlexander Kabaev       _M_release() // nothrow
141f8a1b7d9SAlexander Kabaev       {
142f8a1b7d9SAlexander Kabaev 	if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count,
143f8a1b7d9SAlexander Kabaev 						   -1) == 1)
144f8a1b7d9SAlexander Kabaev 	  {
145f8a1b7d9SAlexander Kabaev 	    _M_dispose();
146f8a1b7d9SAlexander Kabaev #ifdef __GTHREADS
147f8a1b7d9SAlexander Kabaev 	    _GLIBCXX_READ_MEM_BARRIER;
148f8a1b7d9SAlexander Kabaev 	    _GLIBCXX_WRITE_MEM_BARRIER;
149f8a1b7d9SAlexander Kabaev #endif
150f8a1b7d9SAlexander Kabaev 	    if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
151f8a1b7d9SAlexander Kabaev 						       -1) == 1)
152f8a1b7d9SAlexander Kabaev 	      _M_destroy();
153f8a1b7d9SAlexander Kabaev 	  }
154f8a1b7d9SAlexander Kabaev       }
155f8a1b7d9SAlexander Kabaev 
156f8a1b7d9SAlexander Kabaev       void
_M_weak_add_ref()157f8a1b7d9SAlexander Kabaev       _M_weak_add_ref() // nothrow
158f8a1b7d9SAlexander Kabaev       { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); }
159f8a1b7d9SAlexander Kabaev 
160f8a1b7d9SAlexander Kabaev       void
_M_weak_release()161f8a1b7d9SAlexander Kabaev       _M_weak_release() // nothrow
162f8a1b7d9SAlexander Kabaev       {
163f8a1b7d9SAlexander Kabaev 	if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
164f8a1b7d9SAlexander Kabaev 	  {
165f8a1b7d9SAlexander Kabaev #ifdef __GTHREADS
166f8a1b7d9SAlexander Kabaev 	    _GLIBCXX_READ_MEM_BARRIER;
167f8a1b7d9SAlexander Kabaev 	    _GLIBCXX_WRITE_MEM_BARRIER;
168f8a1b7d9SAlexander Kabaev #endif
169f8a1b7d9SAlexander Kabaev 	    _M_destroy();
170f8a1b7d9SAlexander Kabaev 	  }
171f8a1b7d9SAlexander Kabaev       }
172f8a1b7d9SAlexander Kabaev 
173f8a1b7d9SAlexander Kabaev       long
_M_get_use_count()174f8a1b7d9SAlexander Kabaev       _M_get_use_count() const // nothrow
175f8a1b7d9SAlexander Kabaev       { return _M_use_count; }  // XXX is this MT safe?
176f8a1b7d9SAlexander Kabaev 
177f8a1b7d9SAlexander Kabaev     private:
178f8a1b7d9SAlexander Kabaev       _Sp_counted_base(_Sp_counted_base const&);
179f8a1b7d9SAlexander Kabaev       _Sp_counted_base& operator=(_Sp_counted_base const&);
180f8a1b7d9SAlexander Kabaev 
181f8a1b7d9SAlexander Kabaev       _Atomic_word  _M_use_count;     // #shared
182f8a1b7d9SAlexander Kabaev       _Atomic_word  _M_weak_count;    // #weak + (#shared != 0)
183f8a1b7d9SAlexander Kabaev     };
184f8a1b7d9SAlexander Kabaev 
185f8a1b7d9SAlexander Kabaev   template<>
186f8a1b7d9SAlexander Kabaev     inline void
187f8a1b7d9SAlexander Kabaev     _Sp_counted_base<_S_single>::
_M_add_ref_lock()188f8a1b7d9SAlexander Kabaev     _M_add_ref_lock()
189f8a1b7d9SAlexander Kabaev     {
190f8a1b7d9SAlexander Kabaev       if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
191f8a1b7d9SAlexander Kabaev 	{
192f8a1b7d9SAlexander Kabaev 	  _M_use_count = 0;
193f8a1b7d9SAlexander Kabaev 	  __throw_bad_weak_ptr();
194f8a1b7d9SAlexander Kabaev 	}
195f8a1b7d9SAlexander Kabaev     }
196f8a1b7d9SAlexander Kabaev 
197f8a1b7d9SAlexander Kabaev #ifdef __GTHREADS
198f8a1b7d9SAlexander Kabaev   template<>
199f8a1b7d9SAlexander Kabaev     inline void
200f8a1b7d9SAlexander Kabaev     _Sp_counted_base<_S_mutex>::
_M_add_ref_lock()201f8a1b7d9SAlexander Kabaev     _M_add_ref_lock()
202f8a1b7d9SAlexander Kabaev     {
203f8a1b7d9SAlexander Kabaev       __gnu_cxx::__scoped_lock sentry(*this);
204f8a1b7d9SAlexander Kabaev       if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
205f8a1b7d9SAlexander Kabaev 	{
206f8a1b7d9SAlexander Kabaev 	  _M_use_count = 0;
207f8a1b7d9SAlexander Kabaev 	  __throw_bad_weak_ptr();
208f8a1b7d9SAlexander Kabaev 	}
209f8a1b7d9SAlexander Kabaev     }
210f8a1b7d9SAlexander Kabaev #endif
211f8a1b7d9SAlexander Kabaev 
212f8a1b7d9SAlexander Kabaev   template<>
213f8a1b7d9SAlexander Kabaev     inline void
214f8a1b7d9SAlexander Kabaev     _Sp_counted_base<_S_atomic>::
_M_add_ref_lock()215f8a1b7d9SAlexander Kabaev     _M_add_ref_lock()
216f8a1b7d9SAlexander Kabaev     {
217f8a1b7d9SAlexander Kabaev       // Perform lock-free add-if-not-zero operation.
218f8a1b7d9SAlexander Kabaev       _Atomic_word __count;
219f8a1b7d9SAlexander Kabaev       do
220f8a1b7d9SAlexander Kabaev 	{
221f8a1b7d9SAlexander Kabaev 	  __count = _M_use_count;
222f8a1b7d9SAlexander Kabaev 	  if (__count == 0)
223f8a1b7d9SAlexander Kabaev 	    __throw_bad_weak_ptr();
224f8a1b7d9SAlexander Kabaev 
225f8a1b7d9SAlexander Kabaev 	  // Replace the current counter value with the old value + 1, as
226f8a1b7d9SAlexander Kabaev 	  // long as it's not changed meanwhile.
227f8a1b7d9SAlexander Kabaev 	}
228f8a1b7d9SAlexander Kabaev       while (!__sync_bool_compare_and_swap(&_M_use_count, __count,
229f8a1b7d9SAlexander Kabaev 					   __count + 1));
230f8a1b7d9SAlexander Kabaev     }
231f8a1b7d9SAlexander Kabaev 
232f8a1b7d9SAlexander Kabaev   template<typename _Ptr, typename _Deleter, _Lock_policy _Lp>
233f8a1b7d9SAlexander Kabaev     class _Sp_counted_base_impl
234f8a1b7d9SAlexander Kabaev     : public _Sp_counted_base<_Lp>
235f8a1b7d9SAlexander Kabaev     {
236f8a1b7d9SAlexander Kabaev     public:
237f8a1b7d9SAlexander Kabaev       /**
238f8a1b7d9SAlexander Kabaev        *  @brief
239f8a1b7d9SAlexander Kabaev        *  @pre     __d(__p) must not throw.
240f8a1b7d9SAlexander Kabaev        */
_Sp_counted_base_impl(_Ptr __p,_Deleter __d)241f8a1b7d9SAlexander Kabaev       _Sp_counted_base_impl(_Ptr __p, _Deleter __d)
242f8a1b7d9SAlexander Kabaev       : _M_ptr(__p), _M_del(__d) { }
243f8a1b7d9SAlexander Kabaev 
244f8a1b7d9SAlexander Kabaev       virtual void
_M_dispose()245f8a1b7d9SAlexander Kabaev       _M_dispose() // nothrow
246f8a1b7d9SAlexander Kabaev       { _M_del(_M_ptr); }
247f8a1b7d9SAlexander Kabaev 
248f8a1b7d9SAlexander Kabaev       virtual void*
_M_get_deleter(const std::type_info & __ti)249f8a1b7d9SAlexander Kabaev       _M_get_deleter(const std::type_info& __ti)
250f8a1b7d9SAlexander Kabaev       { return __ti == typeid(_Deleter) ? &_M_del : 0; }
251f8a1b7d9SAlexander Kabaev 
252f8a1b7d9SAlexander Kabaev     private:
253f8a1b7d9SAlexander Kabaev       _Sp_counted_base_impl(const _Sp_counted_base_impl&);
254f8a1b7d9SAlexander Kabaev       _Sp_counted_base_impl& operator=(const _Sp_counted_base_impl&);
255f8a1b7d9SAlexander Kabaev 
256f8a1b7d9SAlexander Kabaev       _Ptr      _M_ptr;  // copy constructor must not throw
257f8a1b7d9SAlexander Kabaev       _Deleter  _M_del;  // copy constructor must not throw
258f8a1b7d9SAlexander Kabaev     };
259f8a1b7d9SAlexander Kabaev 
260f8a1b7d9SAlexander Kabaev   template<_Lock_policy _Lp = __default_lock_policy>
261f8a1b7d9SAlexander Kabaev     class __weak_count;
262f8a1b7d9SAlexander Kabaev 
263f8a1b7d9SAlexander Kabaev   template<_Lock_policy _Lp = __default_lock_policy>
264f8a1b7d9SAlexander Kabaev     class __shared_count
265f8a1b7d9SAlexander Kabaev     {
266f8a1b7d9SAlexander Kabaev     public:
__shared_count()267f8a1b7d9SAlexander Kabaev       __shared_count()
268f8a1b7d9SAlexander Kabaev       : _M_pi(0) // nothrow
269f8a1b7d9SAlexander Kabaev       { }
270f8a1b7d9SAlexander Kabaev 
271f8a1b7d9SAlexander Kabaev       template<typename _Ptr, typename _Deleter>
__shared_count(_Ptr __p,_Deleter __d)272f8a1b7d9SAlexander Kabaev         __shared_count(_Ptr __p, _Deleter __d) : _M_pi(0)
273f8a1b7d9SAlexander Kabaev         {
274f8a1b7d9SAlexander Kabaev 	  try
275f8a1b7d9SAlexander Kabaev 	    {
276f8a1b7d9SAlexander Kabaev 	      _M_pi = new _Sp_counted_base_impl<_Ptr, _Deleter, _Lp>(__p, __d);
277f8a1b7d9SAlexander Kabaev 	    }
278f8a1b7d9SAlexander Kabaev 	  catch(...)
279f8a1b7d9SAlexander Kabaev 	    {
280f8a1b7d9SAlexander Kabaev 	      __d(__p); // Call _Deleter on __p.
281f8a1b7d9SAlexander Kabaev 	      __throw_exception_again;
282f8a1b7d9SAlexander Kabaev 	    }
283f8a1b7d9SAlexander Kabaev 	}
284f8a1b7d9SAlexander Kabaev 
285f8a1b7d9SAlexander Kabaev       // Special case for auto_ptr<_Tp> to provide the strong guarantee.
286f8a1b7d9SAlexander Kabaev       template<typename _Tp>
287f8a1b7d9SAlexander Kabaev         explicit
__shared_count(std::auto_ptr<_Tp> & __r)288f8a1b7d9SAlexander Kabaev         __shared_count(std::auto_ptr<_Tp>& __r)
289f8a1b7d9SAlexander Kabaev 	: _M_pi(new _Sp_counted_base_impl<_Tp*,
290f8a1b7d9SAlexander Kabaev 		_Sp_deleter<_Tp>, _Lp >(__r.get(), _Sp_deleter<_Tp>()))
291f8a1b7d9SAlexander Kabaev         { __r.release(); }
292f8a1b7d9SAlexander Kabaev 
293f8a1b7d9SAlexander Kabaev       // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
294f8a1b7d9SAlexander Kabaev       explicit
295f8a1b7d9SAlexander Kabaev       __shared_count(const __weak_count<_Lp>& __r);
296f8a1b7d9SAlexander Kabaev 
~__shared_count()297f8a1b7d9SAlexander Kabaev       ~__shared_count() // nothrow
298f8a1b7d9SAlexander Kabaev       {
299f8a1b7d9SAlexander Kabaev 	if (_M_pi != 0)
300f8a1b7d9SAlexander Kabaev 	  _M_pi->_M_release();
301f8a1b7d9SAlexander Kabaev       }
302f8a1b7d9SAlexander Kabaev 
__shared_count(const __shared_count & __r)303f8a1b7d9SAlexander Kabaev       __shared_count(const __shared_count& __r)
304f8a1b7d9SAlexander Kabaev       : _M_pi(__r._M_pi) // nothrow
305f8a1b7d9SAlexander Kabaev       {
306f8a1b7d9SAlexander Kabaev 	if (_M_pi != 0)
307f8a1b7d9SAlexander Kabaev 	  _M_pi->_M_add_ref_copy();
308f8a1b7d9SAlexander Kabaev       }
309f8a1b7d9SAlexander Kabaev 
310f8a1b7d9SAlexander Kabaev       __shared_count&
311f8a1b7d9SAlexander Kabaev       operator=(const __shared_count& __r) // nothrow
312f8a1b7d9SAlexander Kabaev       {
313f8a1b7d9SAlexander Kabaev 	_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
314f8a1b7d9SAlexander Kabaev 	if (__tmp != _M_pi)
315f8a1b7d9SAlexander Kabaev 	  {
316f8a1b7d9SAlexander Kabaev 	    if (__tmp != 0)
317f8a1b7d9SAlexander Kabaev 	      __tmp->_M_add_ref_copy();
318f8a1b7d9SAlexander Kabaev 	    if (_M_pi != 0)
319f8a1b7d9SAlexander Kabaev 	      _M_pi->_M_release();
320f8a1b7d9SAlexander Kabaev 	    _M_pi = __tmp;
321f8a1b7d9SAlexander Kabaev 	  }
322f8a1b7d9SAlexander Kabaev 	return *this;
323f8a1b7d9SAlexander Kabaev       }
324f8a1b7d9SAlexander Kabaev 
325f8a1b7d9SAlexander Kabaev       void
_M_swap(__shared_count & __r)326f8a1b7d9SAlexander Kabaev       _M_swap(__shared_count& __r) // nothrow
327f8a1b7d9SAlexander Kabaev       {
328f8a1b7d9SAlexander Kabaev 	_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
329f8a1b7d9SAlexander Kabaev 	__r._M_pi = _M_pi;
330f8a1b7d9SAlexander Kabaev 	_M_pi = __tmp;
331f8a1b7d9SAlexander Kabaev       }
332f8a1b7d9SAlexander Kabaev 
333f8a1b7d9SAlexander Kabaev       long
_M_get_use_count()334f8a1b7d9SAlexander Kabaev       _M_get_use_count() const // nothrow
335f8a1b7d9SAlexander Kabaev       { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
336f8a1b7d9SAlexander Kabaev 
337f8a1b7d9SAlexander Kabaev       bool
_M_unique()338f8a1b7d9SAlexander Kabaev       _M_unique() const // nothrow
339f8a1b7d9SAlexander Kabaev       { return this->_M_get_use_count() == 1; }
340f8a1b7d9SAlexander Kabaev 
341f8a1b7d9SAlexander Kabaev       friend inline bool
342f8a1b7d9SAlexander Kabaev       operator==(const __shared_count& __a, const __shared_count& __b)
343f8a1b7d9SAlexander Kabaev       { return __a._M_pi == __b._M_pi; }
344f8a1b7d9SAlexander Kabaev 
345f8a1b7d9SAlexander Kabaev       friend inline bool
346f8a1b7d9SAlexander Kabaev       operator<(const __shared_count& __a, const __shared_count& __b)
347f8a1b7d9SAlexander Kabaev       { return std::less<_Sp_counted_base<_Lp>*>()(__a._M_pi, __b._M_pi); }
348f8a1b7d9SAlexander Kabaev 
349f8a1b7d9SAlexander Kabaev       void*
_M_get_deleter(const std::type_info & __ti)350f8a1b7d9SAlexander Kabaev       _M_get_deleter(const std::type_info& __ti) const
351f8a1b7d9SAlexander Kabaev       { return _M_pi ? _M_pi->_M_get_deleter(__ti) : 0; }
352f8a1b7d9SAlexander Kabaev 
353f8a1b7d9SAlexander Kabaev     private:
354f8a1b7d9SAlexander Kabaev       friend class __weak_count<_Lp>;
355f8a1b7d9SAlexander Kabaev 
356f8a1b7d9SAlexander Kabaev       _Sp_counted_base<_Lp>*  _M_pi;
357f8a1b7d9SAlexander Kabaev     };
358f8a1b7d9SAlexander Kabaev 
359f8a1b7d9SAlexander Kabaev   template<_Lock_policy _Lp>
360f8a1b7d9SAlexander Kabaev     class __weak_count
361f8a1b7d9SAlexander Kabaev     {
362f8a1b7d9SAlexander Kabaev     public:
__weak_count()363f8a1b7d9SAlexander Kabaev       __weak_count()
364f8a1b7d9SAlexander Kabaev       : _M_pi(0) // nothrow
365f8a1b7d9SAlexander Kabaev       { }
366f8a1b7d9SAlexander Kabaev 
__weak_count(const __shared_count<_Lp> & __r)367f8a1b7d9SAlexander Kabaev       __weak_count(const __shared_count<_Lp>& __r)
368f8a1b7d9SAlexander Kabaev       : _M_pi(__r._M_pi) // nothrow
369f8a1b7d9SAlexander Kabaev       {
370f8a1b7d9SAlexander Kabaev 	if (_M_pi != 0)
371f8a1b7d9SAlexander Kabaev 	  _M_pi->_M_weak_add_ref();
372f8a1b7d9SAlexander Kabaev       }
373f8a1b7d9SAlexander Kabaev 
__weak_count(const __weak_count<_Lp> & __r)374f8a1b7d9SAlexander Kabaev       __weak_count(const __weak_count<_Lp>& __r)
375f8a1b7d9SAlexander Kabaev       : _M_pi(__r._M_pi) // nothrow
376f8a1b7d9SAlexander Kabaev       {
377f8a1b7d9SAlexander Kabaev 	if (_M_pi != 0)
378f8a1b7d9SAlexander Kabaev 	  _M_pi->_M_weak_add_ref();
379f8a1b7d9SAlexander Kabaev       }
380f8a1b7d9SAlexander Kabaev 
~__weak_count()381f8a1b7d9SAlexander Kabaev       ~__weak_count() // nothrow
382f8a1b7d9SAlexander Kabaev       {
383f8a1b7d9SAlexander Kabaev 	if (_M_pi != 0)
384f8a1b7d9SAlexander Kabaev 	  _M_pi->_M_weak_release();
385f8a1b7d9SAlexander Kabaev       }
386f8a1b7d9SAlexander Kabaev 
387f8a1b7d9SAlexander Kabaev       __weak_count<_Lp>&
388f8a1b7d9SAlexander Kabaev       operator=(const __shared_count<_Lp>& __r) // nothrow
389f8a1b7d9SAlexander Kabaev       {
390f8a1b7d9SAlexander Kabaev 	_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
391f8a1b7d9SAlexander Kabaev 	if (__tmp != 0)
392f8a1b7d9SAlexander Kabaev 	  __tmp->_M_weak_add_ref();
393f8a1b7d9SAlexander Kabaev 	if (_M_pi != 0)
394f8a1b7d9SAlexander Kabaev 	  _M_pi->_M_weak_release();
395f8a1b7d9SAlexander Kabaev 	_M_pi = __tmp;
396f8a1b7d9SAlexander Kabaev 	return *this;
397f8a1b7d9SAlexander Kabaev       }
398f8a1b7d9SAlexander Kabaev 
399f8a1b7d9SAlexander Kabaev       __weak_count<_Lp>&
400f8a1b7d9SAlexander Kabaev       operator=(const __weak_count<_Lp>& __r) // nothrow
401f8a1b7d9SAlexander Kabaev       {
402f8a1b7d9SAlexander Kabaev 	_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
403f8a1b7d9SAlexander Kabaev 	if (__tmp != 0)
404f8a1b7d9SAlexander Kabaev 	  __tmp->_M_weak_add_ref();
405f8a1b7d9SAlexander Kabaev 	if (_M_pi != 0)
406f8a1b7d9SAlexander Kabaev 	  _M_pi->_M_weak_release();
407f8a1b7d9SAlexander Kabaev 	_M_pi = __tmp;
408f8a1b7d9SAlexander Kabaev 	return *this;
409f8a1b7d9SAlexander Kabaev       }
410f8a1b7d9SAlexander Kabaev 
411f8a1b7d9SAlexander Kabaev       void
_M_swap(__weak_count<_Lp> & __r)412f8a1b7d9SAlexander Kabaev       _M_swap(__weak_count<_Lp>& __r) // nothrow
413f8a1b7d9SAlexander Kabaev       {
414f8a1b7d9SAlexander Kabaev 	_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
415f8a1b7d9SAlexander Kabaev 	__r._M_pi = _M_pi;
416f8a1b7d9SAlexander Kabaev 	_M_pi = __tmp;
417f8a1b7d9SAlexander Kabaev       }
418f8a1b7d9SAlexander Kabaev 
419f8a1b7d9SAlexander Kabaev       long
_M_get_use_count()420f8a1b7d9SAlexander Kabaev       _M_get_use_count() const // nothrow
421f8a1b7d9SAlexander Kabaev       { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
422f8a1b7d9SAlexander Kabaev 
423f8a1b7d9SAlexander Kabaev       friend inline bool
424f8a1b7d9SAlexander Kabaev       operator==(const __weak_count<_Lp>& __a, const __weak_count<_Lp>& __b)
425f8a1b7d9SAlexander Kabaev       { return __a._M_pi == __b._M_pi; }
426f8a1b7d9SAlexander Kabaev 
427f8a1b7d9SAlexander Kabaev       friend inline bool
428f8a1b7d9SAlexander Kabaev       operator<(const __weak_count<_Lp>& __a, const __weak_count<_Lp>& __b)
429f8a1b7d9SAlexander Kabaev       { return std::less<_Sp_counted_base<_Lp>*>()(__a._M_pi, __b._M_pi); }
430f8a1b7d9SAlexander Kabaev 
431f8a1b7d9SAlexander Kabaev     private:
432f8a1b7d9SAlexander Kabaev       friend class __shared_count<_Lp>;
433f8a1b7d9SAlexander Kabaev 
434f8a1b7d9SAlexander Kabaev       _Sp_counted_base<_Lp>*  _M_pi;
435f8a1b7d9SAlexander Kabaev     };
436f8a1b7d9SAlexander Kabaev 
437f8a1b7d9SAlexander Kabaev   template<_Lock_policy _Lp>
438f8a1b7d9SAlexander Kabaev     inline
439f8a1b7d9SAlexander Kabaev     __shared_count<_Lp>::
__shared_count(const __weak_count<_Lp> & __r)440f8a1b7d9SAlexander Kabaev     __shared_count(const __weak_count<_Lp>& __r)
441f8a1b7d9SAlexander Kabaev     : _M_pi(__r._M_pi)
442f8a1b7d9SAlexander Kabaev     {
443f8a1b7d9SAlexander Kabaev       if (_M_pi != 0)
444f8a1b7d9SAlexander Kabaev 	_M_pi->_M_add_ref_lock();
445f8a1b7d9SAlexander Kabaev       else
446f8a1b7d9SAlexander Kabaev 	__throw_bad_weak_ptr();
447f8a1b7d9SAlexander Kabaev     }
448f8a1b7d9SAlexander Kabaev 
449f8a1b7d9SAlexander Kabaev 
450f8a1b7d9SAlexander Kabaev   // Forward declarations.
451f8a1b7d9SAlexander Kabaev   template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
452f8a1b7d9SAlexander Kabaev     class __shared_ptr;
453f8a1b7d9SAlexander Kabaev 
454f8a1b7d9SAlexander Kabaev   template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
455f8a1b7d9SAlexander Kabaev     class __weak_ptr;
456f8a1b7d9SAlexander Kabaev 
457f8a1b7d9SAlexander Kabaev   template<typename _Tp, _Lock_policy _Lp = __default_lock_policy>
458f8a1b7d9SAlexander Kabaev     class __enable_shared_from_this;
459f8a1b7d9SAlexander Kabaev 
460f8a1b7d9SAlexander Kabaev   template<typename _Tp>
461f8a1b7d9SAlexander Kabaev     class shared_ptr;
462f8a1b7d9SAlexander Kabaev 
463f8a1b7d9SAlexander Kabaev   template<typename _Tp>
464f8a1b7d9SAlexander Kabaev     class weak_ptr;
465f8a1b7d9SAlexander Kabaev 
466f8a1b7d9SAlexander Kabaev   template<typename _Tp>
467f8a1b7d9SAlexander Kabaev     class enable_shared_from_this;
468f8a1b7d9SAlexander Kabaev 
469f8a1b7d9SAlexander Kabaev   // Support for enable_shared_from_this.
470f8a1b7d9SAlexander Kabaev 
471f8a1b7d9SAlexander Kabaev   // Friend of __enable_shared_from_this.
472f8a1b7d9SAlexander Kabaev   template<_Lock_policy _Lp, typename _Tp1, typename _Tp2>
473f8a1b7d9SAlexander Kabaev     void
474f8a1b7d9SAlexander Kabaev     __enable_shared_from_this_helper(const __shared_count<_Lp>&,
475f8a1b7d9SAlexander Kabaev 				     const __enable_shared_from_this<_Tp1,
476f8a1b7d9SAlexander Kabaev 				     _Lp>*, const _Tp2*);
477f8a1b7d9SAlexander Kabaev 
478f8a1b7d9SAlexander Kabaev   // Friend of enable_shared_from_this.
479f8a1b7d9SAlexander Kabaev   template<typename _Tp1, typename _Tp2>
480f8a1b7d9SAlexander Kabaev     void
481f8a1b7d9SAlexander Kabaev     __enable_shared_from_this_helper(const __shared_count<>&,
482f8a1b7d9SAlexander Kabaev 				     const enable_shared_from_this<_Tp1>*,
483f8a1b7d9SAlexander Kabaev 				     const _Tp2*);
484f8a1b7d9SAlexander Kabaev 
485f8a1b7d9SAlexander Kabaev   template<_Lock_policy _Lp>
486f8a1b7d9SAlexander Kabaev     inline void
__enable_shared_from_this_helper(const __shared_count<_Lp> &,...)487f8a1b7d9SAlexander Kabaev     __enable_shared_from_this_helper(const __shared_count<_Lp>&, ...)
488f8a1b7d9SAlexander Kabaev     { }
489f8a1b7d9SAlexander Kabaev 
490f8a1b7d9SAlexander Kabaev 
491f8a1b7d9SAlexander Kabaev   struct __static_cast_tag { };
492f8a1b7d9SAlexander Kabaev   struct __const_cast_tag { };
493f8a1b7d9SAlexander Kabaev   struct __dynamic_cast_tag { };
494f8a1b7d9SAlexander Kabaev 
495f8a1b7d9SAlexander Kabaev   /**
496f8a1b7d9SAlexander Kabaev    *  @class shared_ptr <tr1/memory>
497f8a1b7d9SAlexander Kabaev    *
498f8a1b7d9SAlexander Kabaev    *  A smart pointer with reference-counted copy semantics.
499f8a1b7d9SAlexander Kabaev    *  The object pointed to is deleted when the last shared_ptr pointing to
500f8a1b7d9SAlexander Kabaev    *  it is destroyed or reset.
501f8a1b7d9SAlexander Kabaev    */
502f8a1b7d9SAlexander Kabaev   template<typename _Tp, _Lock_policy _Lp>
503f8a1b7d9SAlexander Kabaev     class __shared_ptr
504f8a1b7d9SAlexander Kabaev     {
505f8a1b7d9SAlexander Kabaev     public:
506f8a1b7d9SAlexander Kabaev       typedef _Tp   element_type;
507f8a1b7d9SAlexander Kabaev 
508f8a1b7d9SAlexander Kabaev       /** @brief  Construct an empty %__shared_ptr.
509f8a1b7d9SAlexander Kabaev        *  @post   use_count()==0 && get()==0
510f8a1b7d9SAlexander Kabaev        */
__shared_ptr()511f8a1b7d9SAlexander Kabaev       __shared_ptr()
512f8a1b7d9SAlexander Kabaev       : _M_ptr(0), _M_refcount() // never throws
513f8a1b7d9SAlexander Kabaev       { }
514f8a1b7d9SAlexander Kabaev 
515f8a1b7d9SAlexander Kabaev       /** @brief  Construct a %__shared_ptr that owns the pointer @a __p.
516f8a1b7d9SAlexander Kabaev        *  @param  __p  A pointer that is convertible to element_type*.
517f8a1b7d9SAlexander Kabaev        *  @post   use_count() == 1 && get() == __p
518f8a1b7d9SAlexander Kabaev        *  @throw  std::bad_alloc, in which case @c delete @a __p is called.
519f8a1b7d9SAlexander Kabaev        */
520f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
521f8a1b7d9SAlexander Kabaev         explicit
__shared_ptr(_Tp1 * __p)522f8a1b7d9SAlexander Kabaev         __shared_ptr(_Tp1* __p)
523f8a1b7d9SAlexander Kabaev 	: _M_ptr(__p), _M_refcount(__p, _Sp_deleter<_Tp1>())
524f8a1b7d9SAlexander Kabaev         {
525f8a1b7d9SAlexander Kabaev 	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
526f8a1b7d9SAlexander Kabaev 	  // __glibcxx_function_requires(_CompleteConcept<_Tp1*>)
527f8a1b7d9SAlexander Kabaev 	  __enable_shared_from_this_helper(_M_refcount, __p, __p);
528f8a1b7d9SAlexander Kabaev 	}
529f8a1b7d9SAlexander Kabaev 
530f8a1b7d9SAlexander Kabaev       //
531f8a1b7d9SAlexander Kabaev       // Requirements: _Deleter' copy constructor and destructor must not throw
532f8a1b7d9SAlexander Kabaev       //
533f8a1b7d9SAlexander Kabaev       // __shared_ptr will release __p by calling __d(__p)
534f8a1b7d9SAlexander Kabaev       //
535f8a1b7d9SAlexander Kabaev       /** @brief  Construct a %__shared_ptr that owns the pointer @a __p
536f8a1b7d9SAlexander Kabaev        *          and the deleter @a __d.
537f8a1b7d9SAlexander Kabaev        *  @param  __p  A pointer.
538f8a1b7d9SAlexander Kabaev        *  @param  __d  A deleter.
539f8a1b7d9SAlexander Kabaev        *  @post   use_count() == 1 && get() == __p
540f8a1b7d9SAlexander Kabaev        *  @throw  std::bad_alloc, in which case @a __d(__p) is called.
541f8a1b7d9SAlexander Kabaev        */
542f8a1b7d9SAlexander Kabaev       template<typename _Tp1, typename _Deleter>
__shared_ptr(_Tp1 * __p,_Deleter __d)543f8a1b7d9SAlexander Kabaev         __shared_ptr(_Tp1* __p, _Deleter __d)
544f8a1b7d9SAlexander Kabaev 	: _M_ptr(__p), _M_refcount(__p, __d)
545f8a1b7d9SAlexander Kabaev         {
546f8a1b7d9SAlexander Kabaev 	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
547f8a1b7d9SAlexander Kabaev 	  // TODO requires _Deleter CopyConstructible and __d(__p) well-formed
548f8a1b7d9SAlexander Kabaev 	  __enable_shared_from_this_helper(_M_refcount, __p, __p);
549f8a1b7d9SAlexander Kabaev 	}
550f8a1b7d9SAlexander Kabaev 
551f8a1b7d9SAlexander Kabaev       //  generated copy constructor, assignment, destructor are fine.
552f8a1b7d9SAlexander Kabaev 
553f8a1b7d9SAlexander Kabaev       /** @brief  If @a __r is empty, constructs an empty %__shared_ptr;
554f8a1b7d9SAlexander Kabaev        *          otherwise construct a %__shared_ptr that shares ownership
555f8a1b7d9SAlexander Kabaev        *          with @a __r.
556f8a1b7d9SAlexander Kabaev        *  @param  __r  A %__shared_ptr.
557f8a1b7d9SAlexander Kabaev        *  @post   get() == __r.get() && use_count() == __r.use_count()
558f8a1b7d9SAlexander Kabaev        *  @throw  std::bad_alloc, in which case
559f8a1b7d9SAlexander Kabaev        */
560f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
__shared_ptr(const __shared_ptr<_Tp1,_Lp> & __r)561f8a1b7d9SAlexander Kabaev         __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r)
562f8a1b7d9SAlexander Kabaev 	: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
563f8a1b7d9SAlexander Kabaev         { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) }
564f8a1b7d9SAlexander Kabaev 
565f8a1b7d9SAlexander Kabaev       /** @brief  Constructs a %__shared_ptr that shares ownership with @a __r
566f8a1b7d9SAlexander Kabaev        *          and stores a copy of the pointer stored in @a __r.
567f8a1b7d9SAlexander Kabaev        *  @param  __r  A weak_ptr.
568f8a1b7d9SAlexander Kabaev        *  @post   use_count() == __r.use_count()
569f8a1b7d9SAlexander Kabaev        *  @throw  bad_weak_ptr when __r.expired(),
570f8a1b7d9SAlexander Kabaev        *          in which case the constructor has no effect.
571f8a1b7d9SAlexander Kabaev        */
572f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
573f8a1b7d9SAlexander Kabaev         explicit
__shared_ptr(const __weak_ptr<_Tp1,_Lp> & __r)574f8a1b7d9SAlexander Kabaev         __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
575f8a1b7d9SAlexander Kabaev 	: _M_refcount(__r._M_refcount) // may throw
576f8a1b7d9SAlexander Kabaev         {
577f8a1b7d9SAlexander Kabaev 	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
578f8a1b7d9SAlexander Kabaev 	  // It is now safe to copy __r._M_ptr, as _M_refcount(__r._M_refcount)
579f8a1b7d9SAlexander Kabaev 	  // did not throw.
580f8a1b7d9SAlexander Kabaev 	  _M_ptr = __r._M_ptr;
581f8a1b7d9SAlexander Kabaev 	}
582f8a1b7d9SAlexander Kabaev 
583f8a1b7d9SAlexander Kabaev       /**
584f8a1b7d9SAlexander Kabaev        * @post use_count() == 1 and __r.get() == 0
585f8a1b7d9SAlexander Kabaev        */
586f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
587f8a1b7d9SAlexander Kabaev         explicit
__shared_ptr(std::auto_ptr<_Tp1> & __r)588f8a1b7d9SAlexander Kabaev         __shared_ptr(std::auto_ptr<_Tp1>& __r)
589f8a1b7d9SAlexander Kabaev 	: _M_ptr(__r.get()), _M_refcount()
590f8a1b7d9SAlexander Kabaev         {
591f8a1b7d9SAlexander Kabaev 	  // TODO requires __r.release() convertible to _Tp*, _Tp1 is complete,
592f8a1b7d9SAlexander Kabaev 	  // delete __r.release() well-formed
593f8a1b7d9SAlexander Kabaev 	  _Tp1* __tmp = __r.get();
594f8a1b7d9SAlexander Kabaev 	  _M_refcount = __shared_count<_Lp>(__r);
595f8a1b7d9SAlexander Kabaev 	  __enable_shared_from_this_helper(_M_refcount, __tmp, __tmp);
596f8a1b7d9SAlexander Kabaev 	}
597f8a1b7d9SAlexander Kabaev 
598f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
__shared_ptr(const __shared_ptr<_Tp1,_Lp> & __r,__static_cast_tag)599f8a1b7d9SAlexander Kabaev         __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, __static_cast_tag)
600f8a1b7d9SAlexander Kabaev 	: _M_ptr(static_cast<element_type*>(__r._M_ptr)),
601f8a1b7d9SAlexander Kabaev 	  _M_refcount(__r._M_refcount)
602f8a1b7d9SAlexander Kabaev         { }
603f8a1b7d9SAlexander Kabaev 
604f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
__shared_ptr(const __shared_ptr<_Tp1,_Lp> & __r,__const_cast_tag)605f8a1b7d9SAlexander Kabaev         __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, __const_cast_tag)
606f8a1b7d9SAlexander Kabaev 	: _M_ptr(const_cast<element_type*>(__r._M_ptr)),
607f8a1b7d9SAlexander Kabaev 	  _M_refcount(__r._M_refcount)
608f8a1b7d9SAlexander Kabaev         { }
609f8a1b7d9SAlexander Kabaev 
610f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
__shared_ptr(const __shared_ptr<_Tp1,_Lp> & __r,__dynamic_cast_tag)611f8a1b7d9SAlexander Kabaev         __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, __dynamic_cast_tag)
612f8a1b7d9SAlexander Kabaev 	: _M_ptr(dynamic_cast<element_type*>(__r._M_ptr)),
613f8a1b7d9SAlexander Kabaev 	  _M_refcount(__r._M_refcount)
614f8a1b7d9SAlexander Kabaev         {
615f8a1b7d9SAlexander Kabaev 	  if (_M_ptr == 0) // need to allocate new counter -- the cast failed
616f8a1b7d9SAlexander Kabaev 	    _M_refcount = __shared_count<_Lp>();
617f8a1b7d9SAlexander Kabaev 	}
618f8a1b7d9SAlexander Kabaev 
619f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
620f8a1b7d9SAlexander Kabaev         __shared_ptr&
621f8a1b7d9SAlexander Kabaev         operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws
622f8a1b7d9SAlexander Kabaev         {
623f8a1b7d9SAlexander Kabaev 	  _M_ptr = __r._M_ptr;
624f8a1b7d9SAlexander Kabaev 	  _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
625f8a1b7d9SAlexander Kabaev 	  return *this;
626f8a1b7d9SAlexander Kabaev 	}
627f8a1b7d9SAlexander Kabaev 
628f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
629f8a1b7d9SAlexander Kabaev         __shared_ptr&
630f8a1b7d9SAlexander Kabaev         operator=(std::auto_ptr<_Tp1>& __r)
631f8a1b7d9SAlexander Kabaev         {
632f8a1b7d9SAlexander Kabaev 	  __shared_ptr(__r).swap(*this);
633f8a1b7d9SAlexander Kabaev 	  return *this;
634f8a1b7d9SAlexander Kabaev 	}
635f8a1b7d9SAlexander Kabaev 
636f8a1b7d9SAlexander Kabaev       void
reset()637f8a1b7d9SAlexander Kabaev       reset() // never throws
638f8a1b7d9SAlexander Kabaev       { __shared_ptr().swap(*this); }
639f8a1b7d9SAlexander Kabaev 
640f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
641f8a1b7d9SAlexander Kabaev         void
reset(_Tp1 * __p)642f8a1b7d9SAlexander Kabaev         reset(_Tp1* __p) // _Tp1 must be complete.
643f8a1b7d9SAlexander Kabaev         {
644f8a1b7d9SAlexander Kabaev 	  // Catch self-reset errors.
645f8a1b7d9SAlexander Kabaev 	  _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr);
646f8a1b7d9SAlexander Kabaev 	  __shared_ptr(__p).swap(*this);
647f8a1b7d9SAlexander Kabaev 	}
648f8a1b7d9SAlexander Kabaev 
649f8a1b7d9SAlexander Kabaev       template<typename _Tp1, typename _Deleter>
650f8a1b7d9SAlexander Kabaev         void
reset(_Tp1 * __p,_Deleter __d)651f8a1b7d9SAlexander Kabaev         reset(_Tp1* __p, _Deleter __d)
652f8a1b7d9SAlexander Kabaev         { __shared_ptr(__p, __d).swap(*this); }
653f8a1b7d9SAlexander Kabaev 
654f8a1b7d9SAlexander Kabaev       // Allow class instantiation when _Tp is [cv-qual] void.
655f8a1b7d9SAlexander Kabaev       typename add_reference<_Tp>::type
656f8a1b7d9SAlexander Kabaev       operator*() const // never throws
657f8a1b7d9SAlexander Kabaev       {
658f8a1b7d9SAlexander Kabaev 	_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
659f8a1b7d9SAlexander Kabaev 	return *_M_ptr;
660f8a1b7d9SAlexander Kabaev       }
661f8a1b7d9SAlexander Kabaev 
662f8a1b7d9SAlexander Kabaev       _Tp*
663f8a1b7d9SAlexander Kabaev       operator->() const // never throws
664f8a1b7d9SAlexander Kabaev       {
665f8a1b7d9SAlexander Kabaev 	_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
666f8a1b7d9SAlexander Kabaev 	return _M_ptr;
667f8a1b7d9SAlexander Kabaev       }
668f8a1b7d9SAlexander Kabaev 
669f8a1b7d9SAlexander Kabaev       _Tp*
get()670f8a1b7d9SAlexander Kabaev       get() const // never throws
671f8a1b7d9SAlexander Kabaev       { return _M_ptr; }
672f8a1b7d9SAlexander Kabaev 
673f8a1b7d9SAlexander Kabaev       // Implicit conversion to "bool"
674f8a1b7d9SAlexander Kabaev     private:
675f8a1b7d9SAlexander Kabaev       typedef _Tp* __shared_ptr::*__unspecified_bool_type;
676f8a1b7d9SAlexander Kabaev 
677f8a1b7d9SAlexander Kabaev     public:
__unspecified_bool_type()678f8a1b7d9SAlexander Kabaev       operator __unspecified_bool_type() const // never throws
679f8a1b7d9SAlexander Kabaev       { return _M_ptr == 0 ? 0 : &__shared_ptr::_M_ptr; }
680f8a1b7d9SAlexander Kabaev 
681f8a1b7d9SAlexander Kabaev       bool
unique()682f8a1b7d9SAlexander Kabaev       unique() const // never throws
683f8a1b7d9SAlexander Kabaev       { return _M_refcount._M_unique(); }
684f8a1b7d9SAlexander Kabaev 
685f8a1b7d9SAlexander Kabaev       long
use_count()686f8a1b7d9SAlexander Kabaev       use_count() const // never throws
687f8a1b7d9SAlexander Kabaev       { return _M_refcount._M_get_use_count(); }
688f8a1b7d9SAlexander Kabaev 
689f8a1b7d9SAlexander Kabaev       void
swap(__shared_ptr<_Tp,_Lp> & __other)690f8a1b7d9SAlexander Kabaev       swap(__shared_ptr<_Tp, _Lp>& __other) // never throws
691f8a1b7d9SAlexander Kabaev       {
692f8a1b7d9SAlexander Kabaev 	std::swap(_M_ptr, __other._M_ptr);
693f8a1b7d9SAlexander Kabaev 	_M_refcount._M_swap(__other._M_refcount);
694f8a1b7d9SAlexander Kabaev       }
695f8a1b7d9SAlexander Kabaev 
696f8a1b7d9SAlexander Kabaev     private:
697f8a1b7d9SAlexander Kabaev       void*
_M_get_deleter(const std::type_info & __ti)698f8a1b7d9SAlexander Kabaev       _M_get_deleter(const std::type_info& __ti) const
699f8a1b7d9SAlexander Kabaev       { return _M_refcount._M_get_deleter(__ti); }
700f8a1b7d9SAlexander Kabaev 
701f8a1b7d9SAlexander Kabaev       template<typename _Tp1, _Lock_policy _Lp1>
702f8a1b7d9SAlexander Kabaev         bool
_M_less(const __shared_ptr<_Tp1,_Lp1> & __rhs)703f8a1b7d9SAlexander Kabaev         _M_less(const __shared_ptr<_Tp1, _Lp1>& __rhs) const
704f8a1b7d9SAlexander Kabaev         { return _M_refcount < __rhs._M_refcount; }
705f8a1b7d9SAlexander Kabaev 
706f8a1b7d9SAlexander Kabaev       template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
707f8a1b7d9SAlexander Kabaev       template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
708f8a1b7d9SAlexander Kabaev 
709f8a1b7d9SAlexander Kabaev       template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
710f8a1b7d9SAlexander Kabaev         friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&);
711f8a1b7d9SAlexander Kabaev 
712f8a1b7d9SAlexander Kabaev       // Friends injected into enclosing namespace and found by ADL:
713f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
714f8a1b7d9SAlexander Kabaev         friend inline bool
715f8a1b7d9SAlexander Kabaev         operator==(const __shared_ptr& __a, const __shared_ptr<_Tp1, _Lp>& __b)
716f8a1b7d9SAlexander Kabaev         { return __a.get() == __b.get(); }
717f8a1b7d9SAlexander Kabaev 
718f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
719f8a1b7d9SAlexander Kabaev         friend inline bool
720f8a1b7d9SAlexander Kabaev         operator!=(const __shared_ptr& __a, const __shared_ptr<_Tp1, _Lp>& __b)
721f8a1b7d9SAlexander Kabaev         { return __a.get() != __b.get(); }
722f8a1b7d9SAlexander Kabaev 
723f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
724f8a1b7d9SAlexander Kabaev         friend inline bool
725f8a1b7d9SAlexander Kabaev         operator<(const __shared_ptr& __a, const __shared_ptr<_Tp1, _Lp>& __b)
726f8a1b7d9SAlexander Kabaev         { return __a._M_less(__b); }
727f8a1b7d9SAlexander Kabaev 
728f8a1b7d9SAlexander Kabaev       _Tp*         	   _M_ptr;         // Contained pointer.
729f8a1b7d9SAlexander Kabaev       __shared_count<_Lp>  _M_refcount;    // Reference counter.
730f8a1b7d9SAlexander Kabaev     };
731f8a1b7d9SAlexander Kabaev 
732f8a1b7d9SAlexander Kabaev   // 2.2.3.8 shared_ptr specialized algorithms.
733f8a1b7d9SAlexander Kabaev   template<typename _Tp, _Lock_policy _Lp>
734f8a1b7d9SAlexander Kabaev     inline void
swap(__shared_ptr<_Tp,_Lp> & __a,__shared_ptr<_Tp,_Lp> & __b)735f8a1b7d9SAlexander Kabaev     swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b)
736f8a1b7d9SAlexander Kabaev     { __a.swap(__b); }
737f8a1b7d9SAlexander Kabaev 
738f8a1b7d9SAlexander Kabaev   // 2.2.3.9 shared_ptr casts
739f8a1b7d9SAlexander Kabaev   /** @warning The seemingly equivalent
740f8a1b7d9SAlexander Kabaev    *           <code>shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))</code>
741f8a1b7d9SAlexander Kabaev    *           will eventually result in undefined behaviour,
742f8a1b7d9SAlexander Kabaev    *           attempting to delete the same object twice.
743f8a1b7d9SAlexander Kabaev    */
744f8a1b7d9SAlexander Kabaev   template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
745f8a1b7d9SAlexander Kabaev     __shared_ptr<_Tp, _Lp>
static_pointer_cast(const __shared_ptr<_Tp1,_Lp> & __r)746f8a1b7d9SAlexander Kabaev     static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r)
747f8a1b7d9SAlexander Kabaev     { return __shared_ptr<_Tp, _Lp>(__r, __static_cast_tag()); }
748f8a1b7d9SAlexander Kabaev 
749f8a1b7d9SAlexander Kabaev   /** @warning The seemingly equivalent
750f8a1b7d9SAlexander Kabaev    *           <code>shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))</code>
751f8a1b7d9SAlexander Kabaev    *           will eventually result in undefined behaviour,
752f8a1b7d9SAlexander Kabaev    *           attempting to delete the same object twice.
753f8a1b7d9SAlexander Kabaev    */
754f8a1b7d9SAlexander Kabaev   template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
755f8a1b7d9SAlexander Kabaev     __shared_ptr<_Tp, _Lp>
const_pointer_cast(const __shared_ptr<_Tp1,_Lp> & __r)756f8a1b7d9SAlexander Kabaev     const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r)
757f8a1b7d9SAlexander Kabaev     { return __shared_ptr<_Tp, _Lp>(__r, __const_cast_tag()); }
758f8a1b7d9SAlexander Kabaev 
759f8a1b7d9SAlexander Kabaev   /** @warning The seemingly equivalent
760f8a1b7d9SAlexander Kabaev    *           <code>shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))</code>
761f8a1b7d9SAlexander Kabaev    *           will eventually result in undefined behaviour,
762f8a1b7d9SAlexander Kabaev    *           attempting to delete the same object twice.
763f8a1b7d9SAlexander Kabaev    */
764f8a1b7d9SAlexander Kabaev   template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
765f8a1b7d9SAlexander Kabaev     __shared_ptr<_Tp, _Lp>
dynamic_pointer_cast(const __shared_ptr<_Tp1,_Lp> & __r)766f8a1b7d9SAlexander Kabaev     dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r)
767f8a1b7d9SAlexander Kabaev     { return __shared_ptr<_Tp, _Lp>(__r, __dynamic_cast_tag()); }
768f8a1b7d9SAlexander Kabaev 
769f8a1b7d9SAlexander Kabaev   // 2.2.3.7 shared_ptr I/O
770f8a1b7d9SAlexander Kabaev   template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
771f8a1b7d9SAlexander Kabaev     std::basic_ostream<_Ch, _Tr>&
772f8a1b7d9SAlexander Kabaev     operator<<(std::basic_ostream<_Ch, _Tr>& __os,
773f8a1b7d9SAlexander Kabaev 	       const __shared_ptr<_Tp, _Lp>& __p)
774f8a1b7d9SAlexander Kabaev     {
775f8a1b7d9SAlexander Kabaev       __os << __p.get();
776f8a1b7d9SAlexander Kabaev       return __os;
777f8a1b7d9SAlexander Kabaev     }
778f8a1b7d9SAlexander Kabaev 
779f8a1b7d9SAlexander Kabaev   // 2.2.3.10 shared_ptr get_deleter (experimental)
780f8a1b7d9SAlexander Kabaev   template<typename _Del, typename _Tp, _Lock_policy _Lp>
781f8a1b7d9SAlexander Kabaev     inline _Del*
get_deleter(const __shared_ptr<_Tp,_Lp> & __p)782f8a1b7d9SAlexander Kabaev     get_deleter(const __shared_ptr<_Tp, _Lp>& __p)
783f8a1b7d9SAlexander Kabaev     { return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del))); }
784f8a1b7d9SAlexander Kabaev 
785f8a1b7d9SAlexander Kabaev 
786f8a1b7d9SAlexander Kabaev   template<typename _Tp, _Lock_policy _Lp>
787f8a1b7d9SAlexander Kabaev     class __weak_ptr
788f8a1b7d9SAlexander Kabaev     {
789f8a1b7d9SAlexander Kabaev     public:
790f8a1b7d9SAlexander Kabaev       typedef _Tp element_type;
791f8a1b7d9SAlexander Kabaev 
__weak_ptr()792f8a1b7d9SAlexander Kabaev       __weak_ptr()
793f8a1b7d9SAlexander Kabaev       : _M_ptr(0), _M_refcount() // never throws
794f8a1b7d9SAlexander Kabaev       { }
795f8a1b7d9SAlexander Kabaev 
796f8a1b7d9SAlexander Kabaev       // Generated copy constructor, assignment, destructor are fine.
797f8a1b7d9SAlexander Kabaev 
798f8a1b7d9SAlexander Kabaev       // The "obvious" converting constructor implementation:
799f8a1b7d9SAlexander Kabaev       //
800f8a1b7d9SAlexander Kabaev       //  template<typename _Tp1>
801f8a1b7d9SAlexander Kabaev       //    __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
802f8a1b7d9SAlexander Kabaev       //    : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
803f8a1b7d9SAlexander Kabaev       //    { }
804f8a1b7d9SAlexander Kabaev       //
805f8a1b7d9SAlexander Kabaev       // has a serious problem.
806f8a1b7d9SAlexander Kabaev       //
807f8a1b7d9SAlexander Kabaev       //  __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr)
808f8a1b7d9SAlexander Kabaev       //  conversion may require access to *__r._M_ptr (virtual inheritance).
809f8a1b7d9SAlexander Kabaev       //
810f8a1b7d9SAlexander Kabaev       // It is not possible to avoid spurious access violations since
811f8a1b7d9SAlexander Kabaev       // in multithreaded programs __r._M_ptr may be invalidated at any point.
812f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
__weak_ptr(const __weak_ptr<_Tp1,_Lp> & __r)813f8a1b7d9SAlexander Kabaev         __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
814f8a1b7d9SAlexander Kabaev 	: _M_refcount(__r._M_refcount) // never throws
815f8a1b7d9SAlexander Kabaev         {
816f8a1b7d9SAlexander Kabaev 	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
817f8a1b7d9SAlexander Kabaev 	  _M_ptr = __r.lock().get();
818f8a1b7d9SAlexander Kabaev 	}
819f8a1b7d9SAlexander Kabaev 
820f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
__weak_ptr(const __shared_ptr<_Tp1,_Lp> & __r)821f8a1b7d9SAlexander Kabaev         __weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r)
822f8a1b7d9SAlexander Kabaev 	: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
823f8a1b7d9SAlexander Kabaev         { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) }
824f8a1b7d9SAlexander Kabaev 
825f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
826f8a1b7d9SAlexander Kabaev         __weak_ptr&
827f8a1b7d9SAlexander Kabaev         operator=(const __weak_ptr<_Tp1, _Lp>& __r) // never throws
828f8a1b7d9SAlexander Kabaev         {
829f8a1b7d9SAlexander Kabaev 	  _M_ptr = __r.lock().get();
830f8a1b7d9SAlexander Kabaev 	  _M_refcount = __r._M_refcount;
831f8a1b7d9SAlexander Kabaev 	  return *this;
832f8a1b7d9SAlexander Kabaev 	}
833f8a1b7d9SAlexander Kabaev 
834f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
835f8a1b7d9SAlexander Kabaev         __weak_ptr&
836f8a1b7d9SAlexander Kabaev         operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws
837f8a1b7d9SAlexander Kabaev         {
838f8a1b7d9SAlexander Kabaev 	  _M_ptr = __r._M_ptr;
839f8a1b7d9SAlexander Kabaev 	  _M_refcount = __r._M_refcount;
840f8a1b7d9SAlexander Kabaev 	  return *this;
841f8a1b7d9SAlexander Kabaev 	}
842f8a1b7d9SAlexander Kabaev 
843f8a1b7d9SAlexander Kabaev       __shared_ptr<_Tp, _Lp>
lock()844f8a1b7d9SAlexander Kabaev       lock() const // never throws
845f8a1b7d9SAlexander Kabaev       {
846f8a1b7d9SAlexander Kabaev #ifdef __GTHREADS
847f8a1b7d9SAlexander Kabaev 	// Optimization: avoid throw overhead.
848f8a1b7d9SAlexander Kabaev 	if (expired())
849f8a1b7d9SAlexander Kabaev 	  return __shared_ptr<element_type, _Lp>();
850f8a1b7d9SAlexander Kabaev 
851f8a1b7d9SAlexander Kabaev 	try
852f8a1b7d9SAlexander Kabaev 	  {
853f8a1b7d9SAlexander Kabaev 	    return __shared_ptr<element_type, _Lp>(*this);
854f8a1b7d9SAlexander Kabaev 	  }
855f8a1b7d9SAlexander Kabaev 	catch(const bad_weak_ptr&)
856f8a1b7d9SAlexander Kabaev 	  {
857f8a1b7d9SAlexander Kabaev 	    // Q: How can we get here?
858f8a1b7d9SAlexander Kabaev 	    // A: Another thread may have invalidated r after the
859f8a1b7d9SAlexander Kabaev 	    //    use_count test above.
860*05a636f0SPedro F. Giffuni 	    return __shared_ptr<element_type, _Lp>();
861f8a1b7d9SAlexander Kabaev 	  }
862f8a1b7d9SAlexander Kabaev 
863f8a1b7d9SAlexander Kabaev #else
864f8a1b7d9SAlexander Kabaev 	// Optimization: avoid try/catch overhead when single threaded.
865f8a1b7d9SAlexander Kabaev 	return expired() ? __shared_ptr<element_type, _Lp>()
866f8a1b7d9SAlexander Kabaev 	                 : __shared_ptr<element_type, _Lp>(*this);
867f8a1b7d9SAlexander Kabaev 
868f8a1b7d9SAlexander Kabaev #endif
869f8a1b7d9SAlexander Kabaev       } // XXX MT
870f8a1b7d9SAlexander Kabaev 
871f8a1b7d9SAlexander Kabaev       long
use_count()872f8a1b7d9SAlexander Kabaev       use_count() const // never throws
873f8a1b7d9SAlexander Kabaev       { return _M_refcount._M_get_use_count(); }
874f8a1b7d9SAlexander Kabaev 
875f8a1b7d9SAlexander Kabaev       bool
expired()876f8a1b7d9SAlexander Kabaev       expired() const // never throws
877f8a1b7d9SAlexander Kabaev       { return _M_refcount._M_get_use_count() == 0; }
878f8a1b7d9SAlexander Kabaev 
879f8a1b7d9SAlexander Kabaev       void
reset()880f8a1b7d9SAlexander Kabaev       reset() // never throws
881f8a1b7d9SAlexander Kabaev       { __weak_ptr().swap(*this); }
882f8a1b7d9SAlexander Kabaev 
883f8a1b7d9SAlexander Kabaev       void
swap(__weak_ptr & __s)884f8a1b7d9SAlexander Kabaev       swap(__weak_ptr& __s) // never throws
885f8a1b7d9SAlexander Kabaev       {
886f8a1b7d9SAlexander Kabaev 	std::swap(_M_ptr, __s._M_ptr);
887f8a1b7d9SAlexander Kabaev 	_M_refcount._M_swap(__s._M_refcount);
888f8a1b7d9SAlexander Kabaev       }
889f8a1b7d9SAlexander Kabaev 
890f8a1b7d9SAlexander Kabaev     private:
891f8a1b7d9SAlexander Kabaev       // Used by __enable_shared_from_this.
892f8a1b7d9SAlexander Kabaev       void
_M_assign(_Tp * __ptr,const __shared_count<_Lp> & __refcount)893f8a1b7d9SAlexander Kabaev       _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount)
894f8a1b7d9SAlexander Kabaev       {
895f8a1b7d9SAlexander Kabaev 	_M_ptr = __ptr;
896f8a1b7d9SAlexander Kabaev 	_M_refcount = __refcount;
897f8a1b7d9SAlexander Kabaev       }
898f8a1b7d9SAlexander Kabaev 
899f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
900f8a1b7d9SAlexander Kabaev         bool
_M_less(const __weak_ptr<_Tp1,_Lp> & __rhs)901f8a1b7d9SAlexander Kabaev         _M_less(const __weak_ptr<_Tp1, _Lp>& __rhs) const
902f8a1b7d9SAlexander Kabaev         { return _M_refcount < __rhs._M_refcount; }
903f8a1b7d9SAlexander Kabaev 
904f8a1b7d9SAlexander Kabaev       template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
905f8a1b7d9SAlexander Kabaev       template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
906f8a1b7d9SAlexander Kabaev       friend class __enable_shared_from_this<_Tp, _Lp>;
907f8a1b7d9SAlexander Kabaev       friend class enable_shared_from_this<_Tp>;
908f8a1b7d9SAlexander Kabaev 
909f8a1b7d9SAlexander Kabaev       // Friend injected into namespace and found by ADL.
910f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
911f8a1b7d9SAlexander Kabaev         friend inline bool
912f8a1b7d9SAlexander Kabaev         operator<(const __weak_ptr& __lhs, const __weak_ptr<_Tp1, _Lp>& __rhs)
913f8a1b7d9SAlexander Kabaev         { return __lhs._M_less(__rhs); }
914f8a1b7d9SAlexander Kabaev 
915f8a1b7d9SAlexander Kabaev       _Tp*       	 _M_ptr;         // Contained pointer.
916f8a1b7d9SAlexander Kabaev       __weak_count<_Lp>  _M_refcount;    // Reference counter.
917f8a1b7d9SAlexander Kabaev     };
918f8a1b7d9SAlexander Kabaev 
919f8a1b7d9SAlexander Kabaev   // 2.2.4.7 weak_ptr specialized algorithms.
920f8a1b7d9SAlexander Kabaev   template<typename _Tp, _Lock_policy _Lp>
921f8a1b7d9SAlexander Kabaev     inline void
swap(__weak_ptr<_Tp,_Lp> & __a,__weak_ptr<_Tp,_Lp> & __b)922f8a1b7d9SAlexander Kabaev     swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b)
923f8a1b7d9SAlexander Kabaev     { __a.swap(__b); }
924f8a1b7d9SAlexander Kabaev 
925f8a1b7d9SAlexander Kabaev 
926f8a1b7d9SAlexander Kabaev   template<typename _Tp, _Lock_policy _Lp>
927f8a1b7d9SAlexander Kabaev     class __enable_shared_from_this
928f8a1b7d9SAlexander Kabaev     {
929f8a1b7d9SAlexander Kabaev     protected:
__enable_shared_from_this()930f8a1b7d9SAlexander Kabaev       __enable_shared_from_this() { }
931f8a1b7d9SAlexander Kabaev 
__enable_shared_from_this(const __enable_shared_from_this &)932f8a1b7d9SAlexander Kabaev       __enable_shared_from_this(const __enable_shared_from_this&) { }
933f8a1b7d9SAlexander Kabaev 
934f8a1b7d9SAlexander Kabaev       __enable_shared_from_this&
935f8a1b7d9SAlexander Kabaev       operator=(const __enable_shared_from_this&)
936f8a1b7d9SAlexander Kabaev       { return *this; }
937f8a1b7d9SAlexander Kabaev 
~__enable_shared_from_this()938f8a1b7d9SAlexander Kabaev       ~__enable_shared_from_this() { }
939f8a1b7d9SAlexander Kabaev 
940f8a1b7d9SAlexander Kabaev     public:
941f8a1b7d9SAlexander Kabaev       __shared_ptr<_Tp, _Lp>
shared_from_this()942f8a1b7d9SAlexander Kabaev       shared_from_this()
943f8a1b7d9SAlexander Kabaev       { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); }
944f8a1b7d9SAlexander Kabaev 
945f8a1b7d9SAlexander Kabaev       __shared_ptr<const _Tp, _Lp>
shared_from_this()946f8a1b7d9SAlexander Kabaev       shared_from_this() const
947f8a1b7d9SAlexander Kabaev       { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); }
948f8a1b7d9SAlexander Kabaev 
949f8a1b7d9SAlexander Kabaev     private:
950f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
951f8a1b7d9SAlexander Kabaev         void
_M_weak_assign(_Tp1 * __p,const __shared_count<_Lp> & __n)952f8a1b7d9SAlexander Kabaev         _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const
953f8a1b7d9SAlexander Kabaev         { _M_weak_this._M_assign(__p, __n); }
954f8a1b7d9SAlexander Kabaev 
955f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
956f8a1b7d9SAlexander Kabaev         friend void
__enable_shared_from_this_helper(const __shared_count<_Lp> & __pn,const __enable_shared_from_this * __pe,const _Tp1 * __px)957f8a1b7d9SAlexander Kabaev         __enable_shared_from_this_helper(const __shared_count<_Lp>& __pn,
958f8a1b7d9SAlexander Kabaev 					 const __enable_shared_from_this* __pe,
959f8a1b7d9SAlexander Kabaev 					 const _Tp1* __px)
960f8a1b7d9SAlexander Kabaev         {
961f8a1b7d9SAlexander Kabaev 	  if (__pe != 0)
962f8a1b7d9SAlexander Kabaev 	    __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
963f8a1b7d9SAlexander Kabaev 	}
964f8a1b7d9SAlexander Kabaev 
965f8a1b7d9SAlexander Kabaev       mutable __weak_ptr<_Tp, _Lp>  _M_weak_this;
966f8a1b7d9SAlexander Kabaev     };
967f8a1b7d9SAlexander Kabaev 
968f8a1b7d9SAlexander Kabaev 
969f8a1b7d9SAlexander Kabaev   // The actual TR1 shared_ptr, with forwarding constructors and
970f8a1b7d9SAlexander Kabaev   // assignment operators.
971f8a1b7d9SAlexander Kabaev   template<typename _Tp>
972f8a1b7d9SAlexander Kabaev     class shared_ptr
973f8a1b7d9SAlexander Kabaev     : public __shared_ptr<_Tp>
974f8a1b7d9SAlexander Kabaev     {
975f8a1b7d9SAlexander Kabaev     public:
shared_ptr()976f8a1b7d9SAlexander Kabaev       shared_ptr()
977f8a1b7d9SAlexander Kabaev       : __shared_ptr<_Tp>() { }
978f8a1b7d9SAlexander Kabaev 
979f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
980f8a1b7d9SAlexander Kabaev         explicit
shared_ptr(_Tp1 * __p)981f8a1b7d9SAlexander Kabaev         shared_ptr(_Tp1* __p)
982f8a1b7d9SAlexander Kabaev 	: __shared_ptr<_Tp>(__p) { }
983f8a1b7d9SAlexander Kabaev 
984f8a1b7d9SAlexander Kabaev       template<typename _Tp1, typename _Deleter>
shared_ptr(_Tp1 * __p,_Deleter __d)985f8a1b7d9SAlexander Kabaev         shared_ptr(_Tp1* __p, _Deleter __d)
986f8a1b7d9SAlexander Kabaev 	: __shared_ptr<_Tp>(__p, __d) { }
987f8a1b7d9SAlexander Kabaev 
988f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
shared_ptr(const shared_ptr<_Tp1> & __r)989f8a1b7d9SAlexander Kabaev         shared_ptr(const shared_ptr<_Tp1>& __r)
990f8a1b7d9SAlexander Kabaev 	: __shared_ptr<_Tp>(__r) { }
991f8a1b7d9SAlexander Kabaev 
992f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
993f8a1b7d9SAlexander Kabaev         explicit
shared_ptr(const weak_ptr<_Tp1> & __r)994f8a1b7d9SAlexander Kabaev         shared_ptr(const weak_ptr<_Tp1>& __r)
995f8a1b7d9SAlexander Kabaev 	: __shared_ptr<_Tp>(__r) { }
996f8a1b7d9SAlexander Kabaev 
997f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
998f8a1b7d9SAlexander Kabaev         explicit
shared_ptr(std::auto_ptr<_Tp1> & __r)999f8a1b7d9SAlexander Kabaev         shared_ptr(std::auto_ptr<_Tp1>& __r)
1000f8a1b7d9SAlexander Kabaev 	: __shared_ptr<_Tp>(__r) { }
1001f8a1b7d9SAlexander Kabaev 
1002f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
shared_ptr(const shared_ptr<_Tp1> & __r,__static_cast_tag)1003f8a1b7d9SAlexander Kabaev         shared_ptr(const shared_ptr<_Tp1>& __r, __static_cast_tag)
1004f8a1b7d9SAlexander Kabaev 	: __shared_ptr<_Tp>(__r, __static_cast_tag()) { }
1005f8a1b7d9SAlexander Kabaev 
1006f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
shared_ptr(const shared_ptr<_Tp1> & __r,__const_cast_tag)1007f8a1b7d9SAlexander Kabaev         shared_ptr(const shared_ptr<_Tp1>& __r, __const_cast_tag)
1008f8a1b7d9SAlexander Kabaev 	: __shared_ptr<_Tp>(__r, __const_cast_tag()) { }
1009f8a1b7d9SAlexander Kabaev 
1010f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
shared_ptr(const shared_ptr<_Tp1> & __r,__dynamic_cast_tag)1011f8a1b7d9SAlexander Kabaev         shared_ptr(const shared_ptr<_Tp1>& __r, __dynamic_cast_tag)
1012f8a1b7d9SAlexander Kabaev 	: __shared_ptr<_Tp>(__r, __dynamic_cast_tag()) { }
1013f8a1b7d9SAlexander Kabaev 
1014f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
1015f8a1b7d9SAlexander Kabaev         shared_ptr&
1016f8a1b7d9SAlexander Kabaev         operator=(const shared_ptr<_Tp1>& __r) // never throws
1017f8a1b7d9SAlexander Kabaev         {
1018f8a1b7d9SAlexander Kabaev 	  this->__shared_ptr<_Tp>::operator=(__r);
1019f8a1b7d9SAlexander Kabaev 	  return *this;
1020f8a1b7d9SAlexander Kabaev 	}
1021f8a1b7d9SAlexander Kabaev 
1022f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
1023f8a1b7d9SAlexander Kabaev         shared_ptr&
1024f8a1b7d9SAlexander Kabaev         operator=(std::auto_ptr<_Tp1>& __r)
1025f8a1b7d9SAlexander Kabaev         {
1026f8a1b7d9SAlexander Kabaev 	  this->__shared_ptr<_Tp>::operator=(__r);
1027f8a1b7d9SAlexander Kabaev 	  return *this;
1028f8a1b7d9SAlexander Kabaev 	}
1029f8a1b7d9SAlexander Kabaev     };
1030f8a1b7d9SAlexander Kabaev 
1031f8a1b7d9SAlexander Kabaev   template<typename _Tp, typename _Tp1>
1032f8a1b7d9SAlexander Kabaev     shared_ptr<_Tp>
static_pointer_cast(const shared_ptr<_Tp1> & __r)1033f8a1b7d9SAlexander Kabaev     static_pointer_cast(const shared_ptr<_Tp1>& __r)
1034f8a1b7d9SAlexander Kabaev     { return shared_ptr<_Tp>(__r, __static_cast_tag()); }
1035f8a1b7d9SAlexander Kabaev 
1036f8a1b7d9SAlexander Kabaev   template<typename _Tp, typename _Tp1>
1037f8a1b7d9SAlexander Kabaev     shared_ptr<_Tp>
const_pointer_cast(const shared_ptr<_Tp1> & __r)1038f8a1b7d9SAlexander Kabaev     const_pointer_cast(const shared_ptr<_Tp1>& __r)
1039f8a1b7d9SAlexander Kabaev     { return shared_ptr<_Tp>(__r, __const_cast_tag()); }
1040f8a1b7d9SAlexander Kabaev 
1041f8a1b7d9SAlexander Kabaev   template<typename _Tp, typename _Tp1>
1042f8a1b7d9SAlexander Kabaev     shared_ptr<_Tp>
dynamic_pointer_cast(const shared_ptr<_Tp1> & __r)1043f8a1b7d9SAlexander Kabaev     dynamic_pointer_cast(const shared_ptr<_Tp1>& __r)
1044f8a1b7d9SAlexander Kabaev     { return shared_ptr<_Tp>(__r, __dynamic_cast_tag()); }
1045f8a1b7d9SAlexander Kabaev 
1046f8a1b7d9SAlexander Kabaev 
1047f8a1b7d9SAlexander Kabaev   // The actual TR1 weak_ptr, with forwarding constructors and
1048f8a1b7d9SAlexander Kabaev   // assignment operators.
1049f8a1b7d9SAlexander Kabaev   template<typename _Tp>
1050f8a1b7d9SAlexander Kabaev     class weak_ptr
1051f8a1b7d9SAlexander Kabaev     : public __weak_ptr<_Tp>
1052f8a1b7d9SAlexander Kabaev     {
1053f8a1b7d9SAlexander Kabaev     public:
weak_ptr()1054f8a1b7d9SAlexander Kabaev       weak_ptr()
1055f8a1b7d9SAlexander Kabaev       : __weak_ptr<_Tp>() { }
1056f8a1b7d9SAlexander Kabaev 
1057f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
weak_ptr(const weak_ptr<_Tp1> & __r)1058f8a1b7d9SAlexander Kabaev         weak_ptr(const weak_ptr<_Tp1>& __r)
1059f8a1b7d9SAlexander Kabaev 	: __weak_ptr<_Tp>(__r) { }
1060f8a1b7d9SAlexander Kabaev 
1061f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
weak_ptr(const shared_ptr<_Tp1> & __r)1062f8a1b7d9SAlexander Kabaev         weak_ptr(const shared_ptr<_Tp1>& __r)
1063f8a1b7d9SAlexander Kabaev 	: __weak_ptr<_Tp>(__r) { }
1064f8a1b7d9SAlexander Kabaev 
1065f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
1066f8a1b7d9SAlexander Kabaev         weak_ptr&
1067f8a1b7d9SAlexander Kabaev         operator=(const weak_ptr<_Tp1>& __r) // never throws
1068f8a1b7d9SAlexander Kabaev         {
1069f8a1b7d9SAlexander Kabaev 	  this->__weak_ptr<_Tp>::operator=(__r);
1070f8a1b7d9SAlexander Kabaev 	  return *this;
1071f8a1b7d9SAlexander Kabaev 	}
1072f8a1b7d9SAlexander Kabaev 
1073f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
1074f8a1b7d9SAlexander Kabaev         weak_ptr&
1075f8a1b7d9SAlexander Kabaev         operator=(const shared_ptr<_Tp1>& __r) // never throws
1076f8a1b7d9SAlexander Kabaev         {
1077f8a1b7d9SAlexander Kabaev 	  this->__weak_ptr<_Tp>::operator=(__r);
1078f8a1b7d9SAlexander Kabaev 	  return *this;
1079f8a1b7d9SAlexander Kabaev 	}
1080f8a1b7d9SAlexander Kabaev 
1081f8a1b7d9SAlexander Kabaev       shared_ptr<_Tp>
lock()1082f8a1b7d9SAlexander Kabaev       lock() const // never throws
1083f8a1b7d9SAlexander Kabaev       {
1084f8a1b7d9SAlexander Kabaev #ifdef __GTHREADS
1085f8a1b7d9SAlexander Kabaev 	if (this->expired())
1086f8a1b7d9SAlexander Kabaev 	  return shared_ptr<_Tp>();
1087f8a1b7d9SAlexander Kabaev 
1088f8a1b7d9SAlexander Kabaev 	try
1089f8a1b7d9SAlexander Kabaev 	  {
1090f8a1b7d9SAlexander Kabaev 	    return shared_ptr<_Tp>(*this);
1091f8a1b7d9SAlexander Kabaev 	  }
1092f8a1b7d9SAlexander Kabaev 	catch(const bad_weak_ptr&)
1093f8a1b7d9SAlexander Kabaev 	  {
1094f8a1b7d9SAlexander Kabaev 	    return shared_ptr<_Tp>();
1095f8a1b7d9SAlexander Kabaev 	  }
1096f8a1b7d9SAlexander Kabaev #else
1097f8a1b7d9SAlexander Kabaev 	return this->expired() ? shared_ptr<_Tp>()
1098f8a1b7d9SAlexander Kabaev 	                       : shared_ptr<_Tp>(*this);
1099f8a1b7d9SAlexander Kabaev #endif
1100f8a1b7d9SAlexander Kabaev       }
1101f8a1b7d9SAlexander Kabaev     };
1102f8a1b7d9SAlexander Kabaev 
1103f8a1b7d9SAlexander Kabaev 
1104f8a1b7d9SAlexander Kabaev   template<typename _Tp>
1105f8a1b7d9SAlexander Kabaev     class enable_shared_from_this
1106f8a1b7d9SAlexander Kabaev     {
1107f8a1b7d9SAlexander Kabaev     protected:
enable_shared_from_this()1108f8a1b7d9SAlexander Kabaev       enable_shared_from_this() { }
1109f8a1b7d9SAlexander Kabaev 
enable_shared_from_this(const enable_shared_from_this &)1110f8a1b7d9SAlexander Kabaev       enable_shared_from_this(const enable_shared_from_this&) { }
1111f8a1b7d9SAlexander Kabaev 
1112f8a1b7d9SAlexander Kabaev       enable_shared_from_this&
1113f8a1b7d9SAlexander Kabaev       operator=(const enable_shared_from_this&)
1114f8a1b7d9SAlexander Kabaev       { return *this; }
1115f8a1b7d9SAlexander Kabaev 
~enable_shared_from_this()1116f8a1b7d9SAlexander Kabaev       ~enable_shared_from_this() { }
1117f8a1b7d9SAlexander Kabaev 
1118f8a1b7d9SAlexander Kabaev     public:
1119f8a1b7d9SAlexander Kabaev       shared_ptr<_Tp>
shared_from_this()1120f8a1b7d9SAlexander Kabaev       shared_from_this()
1121f8a1b7d9SAlexander Kabaev       { return shared_ptr<_Tp>(this->_M_weak_this); }
1122f8a1b7d9SAlexander Kabaev 
1123f8a1b7d9SAlexander Kabaev       shared_ptr<const _Tp>
shared_from_this()1124f8a1b7d9SAlexander Kabaev       shared_from_this() const
1125f8a1b7d9SAlexander Kabaev       { return shared_ptr<const _Tp>(this->_M_weak_this); }
1126f8a1b7d9SAlexander Kabaev 
1127f8a1b7d9SAlexander Kabaev     private:
1128f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
1129f8a1b7d9SAlexander Kabaev         void
_M_weak_assign(_Tp1 * __p,const __shared_count<> & __n)1130f8a1b7d9SAlexander Kabaev         _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const
1131f8a1b7d9SAlexander Kabaev         { _M_weak_this._M_assign(__p, __n); }
1132f8a1b7d9SAlexander Kabaev 
1133f8a1b7d9SAlexander Kabaev       template<typename _Tp1>
1134f8a1b7d9SAlexander Kabaev         friend void
__enable_shared_from_this_helper(const __shared_count<> & __pn,const enable_shared_from_this * __pe,const _Tp1 * __px)1135f8a1b7d9SAlexander Kabaev         __enable_shared_from_this_helper(const __shared_count<>& __pn,
1136f8a1b7d9SAlexander Kabaev 					 const enable_shared_from_this* __pe,
1137f8a1b7d9SAlexander Kabaev 					 const _Tp1* __px)
1138f8a1b7d9SAlexander Kabaev         {
1139f8a1b7d9SAlexander Kabaev 	  if (__pe != 0)
1140f8a1b7d9SAlexander Kabaev 	    __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
1141f8a1b7d9SAlexander Kabaev 	}
1142f8a1b7d9SAlexander Kabaev 
1143f8a1b7d9SAlexander Kabaev       mutable weak_ptr<_Tp>  _M_weak_this;
1144f8a1b7d9SAlexander Kabaev     };
1145f8a1b7d9SAlexander Kabaev 
1146f8a1b7d9SAlexander Kabaev _GLIBCXX_END_NAMESPACE
1147f8a1b7d9SAlexander Kabaev } // namespace std
1148f8a1b7d9SAlexander Kabaev 
1149f8a1b7d9SAlexander Kabaev #endif
1150