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