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