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