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