]>
Commit | Line | Data |
---|---|---|
5b9daa7e | 1 | // shared_ptr and weak_ptr implementation -*- C++ -*- |
b758b22a | 2 | |
bc2631e0 | 3 | // Copyright (C) 2007, 2008, 2009 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 | |
748086b7 | 8 | // Free Software Foundation; either version 3, or (at your option) |
b758b22a BK |
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 | ||
748086b7 JJ |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | // You should have received a copy of the GNU General Public License and | |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
b758b22a BK |
24 | |
25 | // shared_count.hpp | |
26 | // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. | |
27 | ||
28 | // shared_ptr.hpp | |
29 | // Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes. | |
30 | // Copyright (C) 2001, 2002, 2003 Peter Dimov | |
31 | ||
32 | // weak_ptr.hpp | |
33 | // Copyright (C) 2001, 2002, 2003 Peter Dimov | |
34 | ||
35 | // enable_shared_from_this.hpp | |
36 | // Copyright (C) 2002 Peter Dimov | |
37 | ||
38 | // Distributed under the Boost Software License, Version 1.0. (See | |
39 | // accompanying file LICENSE_1_0.txt or copy at | |
40 | // http://www.boost.org/LICENSE_1_0.txt) | |
41 | ||
42 | // GCC Note: based on version 1.32.0 of the Boost library. | |
43 | ||
640cbe76 | 44 | /** @file bits/shared_ptr.h |
b758b22a BK |
45 | * This is an internal header file, included by other library headers. |
46 | * You should not attempt to use it directly. | |
47 | */ | |
48 | ||
32fdf2f4 JW |
49 | #ifndef _SHARED_PTR_H |
50 | #define _SHARED_PTR_H 1 | |
51 | ||
640cbe76 JW |
52 | #ifndef __GXX_EXPERIMENTAL_CXX0X__ |
53 | # include <c++0x_warning.h> | |
54 | #endif | |
55 | ||
56 | #if defined(_GLIBCXX_INCLUDE_AS_TR1) | |
57 | # error C++0x header cannot be included from TR1 header | |
58 | #endif | |
aaf0ca6f | 59 | |
5b9daa7e BK |
60 | _GLIBCXX_BEGIN_NAMESPACE(std) |
61 | ||
62 | /** | |
63 | * @addtogroup pointer_abstractions | |
64 | * @{ | |
65 | */ | |
66 | ||
640cbe76 JW |
67 | // counted ptr with no deleter or allocator support |
68 | template<typename _Ptr, _Lock_policy _Lp> | |
69 | class _Sp_counted_ptr | |
70 | : public _Sp_counted_base<_Lp> | |
71 | { | |
72 | public: | |
73 | _Sp_counted_ptr(_Ptr __p) | |
74 | : _M_ptr(__p) { } | |
75 | ||
76 | virtual void | |
77 | _M_dispose() // nothrow | |
78 | { delete _M_ptr; } | |
79 | ||
80 | virtual void | |
81 | _M_destroy() // nothrow | |
82 | { delete this; } | |
83 | ||
84 | virtual void* | |
85 | _M_get_deleter(const std::type_info& __ti) | |
86 | { return 0; } | |
87 | ||
8dd5e93a JW |
88 | _Sp_counted_ptr(const _Sp_counted_ptr&) = delete; |
89 | _Sp_counted_ptr& operator=(const _Sp_counted_ptr&) = delete; | |
640cbe76 JW |
90 | |
91 | protected: | |
92 | _Ptr _M_ptr; // copy constructor must not throw | |
93 | }; | |
94 | ||
95 | // support for custom deleter and/or allocator | |
96 | template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp> | |
97 | class _Sp_counted_deleter | |
98 | : public _Sp_counted_ptr<_Ptr, _Lp> | |
99 | { | |
100 | typedef typename _Alloc::template | |
101 | rebind<_Sp_counted_deleter>::other _My_alloc_type; | |
102 | ||
103 | // Helper class that stores the Deleter and also acts as an allocator. | |
104 | // Used to dispose of the owned pointer and the internal refcount | |
105 | // Requires that copies of _Alloc can free each other's memory. | |
106 | struct _My_Deleter | |
107 | : public _My_alloc_type // copy constructor must not throw | |
108 | { | |
109 | _Deleter _M_del; // copy constructor must not throw | |
110 | _My_Deleter(_Deleter __d, const _Alloc& __a) | |
111 | : _My_alloc_type(__a), _M_del(__d) { } | |
112 | }; | |
113 | ||
114 | protected: | |
115 | typedef _Sp_counted_ptr<_Ptr, _Lp> _Base_type; | |
116 | ||
117 | public: | |
118 | /** | |
119 | * @brief | |
120 | * @pre __d(__p) must not throw. | |
121 | */ | |
122 | _Sp_counted_deleter(_Ptr __p, _Deleter __d) | |
123 | : _Base_type(__p), _M_del(__d, _Alloc()) { } | |
124 | ||
125 | /** | |
126 | * @brief | |
127 | * @pre __d(__p) must not throw. | |
128 | */ | |
129 | _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a) | |
130 | : _Base_type(__p), _M_del(__d, __a) { } | |
131 | ||
132 | virtual void | |
133 | _M_dispose() // nothrow | |
134 | { _M_del._M_del(_Base_type::_M_ptr); } | |
135 | ||
136 | virtual void | |
137 | _M_destroy() // nothrow | |
138 | { | |
139 | _My_alloc_type __a(_M_del); | |
140 | this->~_Sp_counted_deleter(); | |
141 | __a.deallocate(this, 1); | |
142 | } | |
143 | ||
144 | virtual void* | |
145 | _M_get_deleter(const std::type_info& __ti) | |
146 | { return __ti == typeid(_Deleter) ? &_M_del._M_del : 0; } | |
147 | ||
640cbe76 JW |
148 | protected: |
149 | _My_Deleter _M_del; // copy constructor must not throw | |
150 | }; | |
151 | ||
152 | // helpers for make_shared / allocate_shared | |
153 | ||
154 | template<typename _Tp> | |
155 | struct _Sp_destroy_inplace | |
156 | { | |
157 | void operator()(_Tp* __p) const { if (__p) __p->~_Tp(); } | |
158 | }; | |
159 | ||
160 | struct _Sp_make_shared_tag { }; | |
161 | ||
162 | template<typename _Tp, typename _Alloc, _Lock_policy _Lp> | |
163 | class _Sp_counted_ptr_inplace | |
164 | : public _Sp_counted_deleter<_Tp*, _Sp_destroy_inplace<_Tp>, _Alloc, _Lp> | |
165 | { | |
166 | typedef _Sp_counted_deleter<_Tp*, _Sp_destroy_inplace<_Tp>, _Alloc, _Lp> | |
167 | _Base_type; | |
168 | ||
169 | public: | |
170 | _Sp_counted_ptr_inplace(_Alloc __a) | |
171 | : _Base_type(static_cast<_Tp*>(0), _Sp_destroy_inplace<_Tp>(), __a) | |
172 | , _M_storage() | |
173 | { | |
174 | void* __p = &_M_storage; | |
175 | ::new (__p) _Tp(); // might throw | |
176 | _Base_type::_Base_type::_M_ptr = static_cast<_Tp*>(__p); | |
177 | } | |
178 | ||
179 | template<typename... _Args> | |
180 | _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args) | |
181 | : _Base_type(static_cast<_Tp*>(0), _Sp_destroy_inplace<_Tp>(), __a) | |
182 | , _M_storage() | |
183 | { | |
184 | void* __p = &_M_storage; | |
185 | ::new (__p) _Tp(std::forward<_Args>(__args)...); // might throw | |
186 | _Base_type::_Base_type::_M_ptr = static_cast<_Tp*>(__p); | |
187 | } | |
188 | ||
189 | // override because the allocator needs to know the dynamic type | |
190 | virtual void | |
191 | _M_destroy() // nothrow | |
192 | { | |
193 | typedef typename _Alloc::template | |
194 | rebind<_Sp_counted_ptr_inplace>::other _My_alloc_type; | |
195 | _My_alloc_type __a(_Base_type::_M_del); | |
196 | this->~_Sp_counted_ptr_inplace(); | |
197 | __a.deallocate(this, 1); | |
198 | } | |
199 | ||
200 | // sneaky trick so __shared_ptr can get the managed pointer | |
201 | virtual void* | |
202 | _M_get_deleter(const std::type_info& __ti) | |
203 | { | |
204 | return __ti == typeid(_Sp_make_shared_tag) | |
205 | ? static_cast<void*>(&_M_storage) | |
206 | : _Base_type::_M_get_deleter(__ti); | |
207 | } | |
208 | ||
209 | private: | |
210 | typename aligned_storage<sizeof(_Tp), alignment_of<_Tp>::value>::type | |
211 | _M_storage; | |
212 | }; | |
213 | ||
214 | template<_Lock_policy _Lp = __default_lock_policy> | |
215 | class __weak_count; | |
216 | ||
217 | template<_Lock_policy _Lp = __default_lock_policy> | |
218 | class __shared_count | |
219 | { | |
220 | public: | |
221 | __shared_count() | |
222 | : _M_pi(0) // nothrow | |
223 | { } | |
224 | ||
225 | template<typename _Ptr> | |
226 | __shared_count(_Ptr __p) : _M_pi(0) | |
227 | { | |
bc2631e0 | 228 | __try |
640cbe76 JW |
229 | { |
230 | _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p); | |
231 | } | |
bc2631e0 | 232 | __catch(...) |
640cbe76 JW |
233 | { |
234 | delete __p; | |
235 | __throw_exception_again; | |
236 | } | |
237 | } | |
238 | ||
239 | template<typename _Ptr, typename _Deleter> | |
240 | __shared_count(_Ptr __p, _Deleter __d) : _M_pi(0) | |
241 | { | |
242 | // allocator's value_type doesn't matter, will rebind it anyway | |
243 | typedef std::allocator<int> _Alloc; | |
244 | typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type; | |
245 | typedef std::allocator<_Sp_cd_type> _Alloc2; | |
246 | _Alloc2 __a2; | |
bc2631e0 | 247 | __try |
640cbe76 JW |
248 | { |
249 | _M_pi = __a2.allocate(1); | |
c78a2119 | 250 | ::new(static_cast<void*>(_M_pi)) _Sp_cd_type(__p, __d); |
640cbe76 | 251 | } |
bc2631e0 | 252 | __catch(...) |
640cbe76 JW |
253 | { |
254 | __d(__p); // Call _Deleter on __p. | |
255 | if (_M_pi) | |
256 | __a2.deallocate(static_cast<_Sp_cd_type*>(_M_pi), 1); | |
257 | __throw_exception_again; | |
258 | } | |
259 | } | |
260 | ||
261 | template<typename _Ptr, typename _Deleter, typename _Alloc> | |
262 | __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0) | |
263 | { | |
264 | typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type; | |
265 | typedef typename _Alloc::template rebind<_Sp_cd_type>::other _Alloc2; | |
266 | _Alloc2 __a2(__a); | |
bc2631e0 | 267 | __try |
640cbe76 JW |
268 | { |
269 | _M_pi = __a2.allocate(1); | |
c78a2119 | 270 | ::new(static_cast<void*>(_M_pi)) _Sp_cd_type(__p, __d, __a); |
640cbe76 | 271 | } |
bc2631e0 | 272 | __catch(...) |
640cbe76 JW |
273 | { |
274 | __d(__p); // Call _Deleter on __p. | |
275 | if (_M_pi) | |
276 | __a2.deallocate(static_cast<_Sp_cd_type*>(_M_pi), 1); | |
277 | __throw_exception_again; | |
278 | } | |
279 | } | |
280 | ||
281 | template<typename _Tp, typename _Alloc, typename... _Args> | |
282 | __shared_count(_Sp_make_shared_tag, _Tp*, _Alloc __a, _Args&&... __args) | |
283 | : _M_pi(0) | |
284 | { | |
285 | typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type; | |
286 | typedef typename _Alloc::template rebind<_Sp_cp_type>::other _Alloc2; | |
287 | _Alloc2 __a2(__a); | |
bc2631e0 | 288 | __try |
640cbe76 JW |
289 | { |
290 | _M_pi = __a2.allocate(1); | |
c78a2119 PC |
291 | ::new(static_cast<void*>(_M_pi)) _Sp_cp_type(__a, |
292 | std::forward<_Args>(__args)...); | |
640cbe76 | 293 | } |
bc2631e0 | 294 | __catch(...) |
640cbe76 JW |
295 | { |
296 | if (_M_pi) | |
297 | __a2.deallocate(static_cast<_Sp_cp_type*>(_M_pi), 1); | |
298 | __throw_exception_again; | |
299 | } | |
300 | } | |
301 | ||
302 | #if _GLIBCXX_DEPRECATED | |
303 | // Special case for auto_ptr<_Tp> to provide the strong guarantee. | |
304 | template<typename _Tp> | |
305 | explicit | |
306 | __shared_count(std::auto_ptr<_Tp>&& __r) | |
307 | : _M_pi(new _Sp_counted_ptr<_Tp*, _Lp>(__r.get())) | |
308 | { __r.release(); } | |
309 | #endif | |
310 | ||
311 | // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee. | |
312 | template<typename _Tp, typename _Del> | |
313 | explicit | |
314 | __shared_count(std::unique_ptr<_Tp, _Del>&& __r) | |
315 | : _M_pi(_S_create_from_up(std::move(__r))) | |
316 | { __r.release(); } | |
317 | ||
318 | // Throw bad_weak_ptr when __r._M_get_use_count() == 0. | |
319 | explicit | |
320 | __shared_count(const __weak_count<_Lp>& __r); | |
321 | ||
322 | ~__shared_count() // nothrow | |
323 | { | |
324 | if (_M_pi != 0) | |
325 | _M_pi->_M_release(); | |
326 | } | |
327 | ||
328 | __shared_count(const __shared_count& __r) | |
329 | : _M_pi(__r._M_pi) // nothrow | |
330 | { | |
331 | if (_M_pi != 0) | |
332 | _M_pi->_M_add_ref_copy(); | |
333 | } | |
334 | ||
335 | __shared_count& | |
336 | operator=(const __shared_count& __r) // nothrow | |
337 | { | |
338 | _Sp_counted_base<_Lp>* __tmp = __r._M_pi; | |
339 | if (__tmp != _M_pi) | |
340 | { | |
341 | if (__tmp != 0) | |
342 | __tmp->_M_add_ref_copy(); | |
343 | if (_M_pi != 0) | |
344 | _M_pi->_M_release(); | |
345 | _M_pi = __tmp; | |
346 | } | |
347 | return *this; | |
348 | } | |
349 | ||
350 | void | |
351 | _M_swap(__shared_count& __r) // nothrow | |
352 | { | |
353 | _Sp_counted_base<_Lp>* __tmp = __r._M_pi; | |
354 | __r._M_pi = _M_pi; | |
355 | _M_pi = __tmp; | |
356 | } | |
357 | ||
358 | long | |
359 | _M_get_use_count() const // nothrow | |
360 | { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; } | |
361 | ||
362 | bool | |
363 | _M_unique() const // nothrow | |
364 | { return this->_M_get_use_count() == 1; } | |
365 | ||
640cbe76 JW |
366 | void* |
367 | _M_get_deleter(const std::type_info& __ti) const | |
368 | { return _M_pi ? _M_pi->_M_get_deleter(__ti) : 0; } | |
369 | ||
8dd5e93a JW |
370 | bool |
371 | _M_less(const __shared_count& __rhs) const | |
372 | { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } | |
373 | ||
374 | bool | |
375 | _M_less(const __weak_count<_Lp>& __rhs) const | |
376 | { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } | |
377 | ||
378 | // friend function injected into enclosing namespace and found by ADL | |
379 | friend inline bool | |
380 | operator==(const __shared_count& __a, const __shared_count& __b) | |
381 | { return __a._M_pi == __b._M_pi; } | |
382 | ||
640cbe76 JW |
383 | private: |
384 | friend class __weak_count<_Lp>; | |
385 | ||
386 | template<typename _Tp, typename _Del> | |
387 | static _Sp_counted_base<_Lp>* | |
388 | _S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r, | |
389 | typename std::enable_if<!std::is_reference<_Del>::value>::type* = 0) | |
390 | { | |
391 | return new _Sp_counted_deleter<_Tp*, _Del, std::allocator<_Tp>, | |
392 | _Lp>(__r.get(), __r.get_deleter()); | |
393 | } | |
394 | ||
395 | template<typename _Tp, typename _Del> | |
396 | static _Sp_counted_base<_Lp>* | |
397 | _S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r, | |
398 | typename std::enable_if<std::is_reference<_Del>::value>::type* = 0) | |
399 | { | |
400 | typedef typename std::remove_reference<_Del>::type _Del1; | |
401 | typedef std::reference_wrapper<_Del1> _Del2; | |
402 | return new _Sp_counted_deleter<_Tp*, _Del2, std::allocator<_Tp>, | |
403 | _Lp>(__r.get(), std::ref(__r.get_deleter())); | |
404 | } | |
405 | ||
406 | _Sp_counted_base<_Lp>* _M_pi; | |
407 | }; | |
408 | ||
b758b22a | 409 | |
459f9f82 | 410 | template<_Lock_policy _Lp> |
c8bd30dd | 411 | class __weak_count |
a25ce4db | 412 | { |
c8bd30dd PC |
413 | public: |
414 | __weak_count() | |
459f9f82 PC |
415 | : _M_pi(0) // nothrow |
416 | { } | |
a25ce4db | 417 | |
c8bd30dd | 418 | __weak_count(const __shared_count<_Lp>& __r) |
459f9f82 PC |
419 | : _M_pi(__r._M_pi) // nothrow |
420 | { | |
421 | if (_M_pi != 0) | |
c8bd30dd | 422 | _M_pi->_M_weak_add_ref(); |
459f9f82 PC |
423 | } |
424 | ||
c8bd30dd | 425 | __weak_count(const __weak_count<_Lp>& __r) |
459f9f82 PC |
426 | : _M_pi(__r._M_pi) // nothrow |
427 | { | |
428 | if (_M_pi != 0) | |
c8bd30dd | 429 | _M_pi->_M_weak_add_ref(); |
459f9f82 PC |
430 | } |
431 | ||
c8bd30dd | 432 | ~__weak_count() // nothrow |
459f9f82 PC |
433 | { |
434 | if (_M_pi != 0) | |
c8bd30dd | 435 | _M_pi->_M_weak_release(); |
459f9f82 PC |
436 | } |
437 | ||
c8bd30dd PC |
438 | __weak_count<_Lp>& |
439 | operator=(const __shared_count<_Lp>& __r) // nothrow | |
459f9f82 PC |
440 | { |
441 | _Sp_counted_base<_Lp>* __tmp = __r._M_pi; | |
442 | if (__tmp != 0) | |
c8bd30dd | 443 | __tmp->_M_weak_add_ref(); |
459f9f82 | 444 | if (_M_pi != 0) |
c8bd30dd | 445 | _M_pi->_M_weak_release(); |
459f9f82 PC |
446 | _M_pi = __tmp; |
447 | return *this; | |
448 | } | |
449 | ||
c8bd30dd PC |
450 | __weak_count<_Lp>& |
451 | operator=(const __weak_count<_Lp>& __r) // nothrow | |
459f9f82 | 452 | { |
c8bd30dd | 453 | _Sp_counted_base<_Lp>* __tmp = __r._M_pi; |
459f9f82 | 454 | if (__tmp != 0) |
c8bd30dd | 455 | __tmp->_M_weak_add_ref(); |
459f9f82 | 456 | if (_M_pi != 0) |
c8bd30dd | 457 | _M_pi->_M_weak_release(); |
459f9f82 PC |
458 | _M_pi = __tmp; |
459 | return *this; | |
460 | } | |
c8bd30dd | 461 | |
459f9f82 | 462 | void |
c8bd30dd | 463 | _M_swap(__weak_count<_Lp>& __r) // nothrow |
459f9f82 | 464 | { |
c8bd30dd | 465 | _Sp_counted_base<_Lp>* __tmp = __r._M_pi; |
459f9f82 PC |
466 | __r._M_pi = _M_pi; |
467 | _M_pi = __tmp; | |
468 | } | |
a25ce4db | 469 | |
459f9f82 | 470 | long |
c8bd30dd PC |
471 | _M_get_use_count() const // nothrow |
472 | { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; } | |
473 | ||
8dd5e93a JW |
474 | bool |
475 | _M_less(const __weak_count& __rhs) const | |
476 | { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } | |
477 | ||
478 | bool | |
479 | _M_less(const __shared_count<_Lp>& __rhs) const | |
480 | { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } | |
481 | ||
482 | // friend function injected into enclosing namespace and found by ADL | |
459f9f82 | 483 | friend inline bool |
8dd5e93a | 484 | operator==(const __weak_count& __a, const __weak_count& __b) |
459f9f82 | 485 | { return __a._M_pi == __b._M_pi; } |
c8bd30dd PC |
486 | |
487 | private: | |
488 | friend class __shared_count<_Lp>; | |
489 | ||
490 | _Sp_counted_base<_Lp>* _M_pi; | |
459f9f82 PC |
491 | }; |
492 | ||
aaf0ca6f | 493 | // now that __weak_count is defined we can define this constructor: |
459f9f82 PC |
494 | template<_Lock_policy _Lp> |
495 | inline | |
c8bd30dd PC |
496 | __shared_count<_Lp>:: |
497 | __shared_count(const __weak_count<_Lp>& __r) | |
459f9f82 | 498 | : _M_pi(__r._M_pi) |
a25ce4db | 499 | { |
a25ce4db | 500 | if (_M_pi != 0) |
c8bd30dd | 501 | _M_pi->_M_add_ref_lock(); |
459f9f82 PC |
502 | else |
503 | __throw_bad_weak_ptr(); | |
a25ce4db | 504 | } |
459f9f82 | 505 | |
c8bd30dd | 506 | // Forward declarations. |
459f9f82 PC |
507 | template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> |
508 | class __shared_ptr; | |
a25ce4db | 509 | |
459f9f82 PC |
510 | template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> |
511 | class __weak_ptr; | |
b758b22a | 512 | |
c8bd30dd | 513 | template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> |
459f9f82 | 514 | class __enable_shared_from_this; |
b758b22a | 515 | |
c8bd30dd PC |
516 | template<typename _Tp> |
517 | class shared_ptr; | |
518 | ||
519 | template<typename _Tp> | |
520 | class weak_ptr; | |
a15024e6 | 521 | |
c8bd30dd PC |
522 | template<typename _Tp> |
523 | class enable_shared_from_this; | |
b758b22a | 524 | |
459f9f82 | 525 | // Support for enable_shared_from_this. |
b758b22a | 526 | |
459f9f82 PC |
527 | // Friend of __enable_shared_from_this. |
528 | template<_Lock_policy _Lp, typename _Tp1, typename _Tp2> | |
529 | void | |
c8bd30dd | 530 | __enable_shared_from_this_helper(const __shared_count<_Lp>&, |
459f9f82 PC |
531 | const __enable_shared_from_this<_Tp1, |
532 | _Lp>*, const _Tp2*); | |
b758b22a | 533 | |
c8bd30dd PC |
534 | // Friend of enable_shared_from_this. |
535 | template<typename _Tp1, typename _Tp2> | |
536 | void | |
537 | __enable_shared_from_this_helper(const __shared_count<>&, | |
538 | const enable_shared_from_this<_Tp1>*, | |
539 | const _Tp2*); | |
540 | ||
459f9f82 PC |
541 | template<_Lock_policy _Lp> |
542 | inline void | |
c8bd30dd | 543 | __enable_shared_from_this_helper(const __shared_count<_Lp>&, ...) |
459f9f82 | 544 | { } |
b758b22a BK |
545 | |
546 | ||
459f9f82 PC |
547 | template<typename _Tp, _Lock_policy _Lp> |
548 | class __shared_ptr | |
549 | { | |
459f9f82 PC |
550 | public: |
551 | typedef _Tp element_type; | |
552 | ||
553 | /** @brief Construct an empty %__shared_ptr. | |
554 | * @post use_count()==0 && get()==0 | |
555 | */ | |
556 | __shared_ptr() | |
557 | : _M_ptr(0), _M_refcount() // never throws | |
558 | { } | |
b758b22a | 559 | |
c8bd30dd PC |
560 | /** @brief Construct a %__shared_ptr that owns the pointer @a __p. |
561 | * @param __p A pointer that is convertible to element_type*. | |
562 | * @post use_count() == 1 && get() == __p | |
563 | * @throw std::bad_alloc, in which case @c delete @a __p is called. | |
459f9f82 PC |
564 | */ |
565 | template<typename _Tp1> | |
566 | explicit | |
567 | __shared_ptr(_Tp1* __p) | |
aaf0ca6f | 568 | : _M_ptr(__p), _M_refcount(__p) |
459f9f82 PC |
569 | { |
570 | __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) | |
571 | // __glibcxx_function_requires(_CompleteConcept<_Tp1*>) | |
c8bd30dd | 572 | __enable_shared_from_this_helper(_M_refcount, __p, __p); |
459f9f82 | 573 | } |
b758b22a | 574 | |
459f9f82 | 575 | // |
939759fc BK |
576 | // Requirements: _Deleter's copy constructor and destructor must |
577 | // not throw | |
459f9f82 | 578 | // |
c8bd30dd | 579 | // __shared_ptr will release __p by calling __d(__p) |
459f9f82 | 580 | // |
c8bd30dd PC |
581 | /** @brief Construct a %__shared_ptr that owns the pointer @a __p |
582 | * and the deleter @a __d. | |
583 | * @param __p A pointer. | |
584 | * @param __d A deleter. | |
585 | * @post use_count() == 1 && get() == __p | |
586 | * @throw std::bad_alloc, in which case @a __d(__p) is called. | |
459f9f82 PC |
587 | */ |
588 | template<typename _Tp1, typename _Deleter> | |
589 | __shared_ptr(_Tp1* __p, _Deleter __d) | |
aaf0ca6f | 590 | : _M_ptr(__p), _M_refcount(__p, __d) |
459f9f82 PC |
591 | { |
592 | __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) | |
c8bd30dd PC |
593 | // TODO requires _Deleter CopyConstructible and __d(__p) well-formed |
594 | __enable_shared_from_this_helper(_M_refcount, __p, __p); | |
459f9f82 PC |
595 | } |
596 | ||
aaf0ca6f | 597 | // |
939759fc BK |
598 | // Requirements: _Deleter's copy constructor and destructor must |
599 | // not throw _Alloc's copy constructor and destructor must not | |
600 | // throw. | |
aaf0ca6f JW |
601 | // |
602 | // __shared_ptr will release __p by calling __d(__p) | |
603 | // | |
604 | /** @brief Construct a %__shared_ptr that owns the pointer @a __p | |
605 | * and the deleter @a __d. | |
606 | * @param __p A pointer. | |
607 | * @param __d A deleter. | |
608 | * @param __a An allocator. | |
609 | * @post use_count() == 1 && get() == __p | |
610 | * @throw std::bad_alloc, in which case @a __d(__p) is called. | |
611 | */ | |
612 | template<typename _Tp1, typename _Deleter, typename _Alloc> | |
613 | __shared_ptr(_Tp1* __p, _Deleter __d, const _Alloc& __a) | |
614 | : _M_ptr(__p), _M_refcount(__p, __d, __a) | |
615 | { | |
616 | __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) | |
617 | // TODO requires _Deleter CopyConstructible and __d(__p) well-formed | |
618 | __enable_shared_from_this_helper(_M_refcount, __p, __p); | |
619 | } | |
620 | ||
621 | /** @brief Constructs a %__shared_ptr instance that stores @a __p | |
622 | * and shares ownership with @a __r. | |
623 | * @param __r A %__shared_ptr. | |
624 | * @param __p A pointer that will remain valid while @a *__r is valid. | |
625 | * @post get() == __p && use_count() == __r.use_count() | |
626 | * | |
627 | * This can be used to construct a @c shared_ptr to a sub-object | |
628 | * of an object managed by an existing @c shared_ptr. | |
629 | * | |
630 | * @code | |
631 | * shared_ptr< pair<int,int> > pii(new pair<int,int>()); | |
632 | * shared_ptr<int> pi(pii, &pii->first); | |
633 | * assert(pii.use_count() == 2); | |
634 | * @endcode | |
635 | */ | |
636 | template<typename _Tp1> | |
637 | __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) | |
638 | : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws | |
639 | { } | |
aaf0ca6f | 640 | |
459f9f82 PC |
641 | // generated copy constructor, assignment, destructor are fine. |
642 | ||
c8bd30dd | 643 | /** @brief If @a __r is empty, constructs an empty %__shared_ptr; |
459f9f82 | 644 | * otherwise construct a %__shared_ptr that shares ownership |
c8bd30dd PC |
645 | * with @a __r. |
646 | * @param __r A %__shared_ptr. | |
647 | * @post get() == __r.get() && use_count() == __r.use_count() | |
459f9f82 PC |
648 | */ |
649 | template<typename _Tp1> | |
650 | __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) | |
651 | : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws | |
652 | { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) } | |
653 | ||
aaf0ca6f JW |
654 | /** @brief Move-constructs a %__shared_ptr instance from @a __r. |
655 | * @param __r A %__shared_ptr rvalue. | |
656 | * @post *this contains the old value of @a __r, @a __r is empty. | |
657 | */ | |
658 | __shared_ptr(__shared_ptr&& __r) | |
659 | : _M_ptr(__r._M_ptr), _M_refcount() // never throws | |
660 | { | |
661 | _M_refcount._M_swap(__r._M_refcount); | |
662 | __r._M_ptr = 0; | |
663 | } | |
664 | ||
665 | /** @brief Move-constructs a %__shared_ptr instance from @a __r. | |
666 | * @param __r A %__shared_ptr rvalue. | |
667 | * @post *this contains the old value of @a __r, @a __r is empty. | |
668 | */ | |
669 | template<typename _Tp1> | |
670 | __shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) | |
671 | : _M_ptr(__r._M_ptr), _M_refcount() // never throws | |
672 | { | |
673 | __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) | |
674 | _M_refcount._M_swap(__r._M_refcount); | |
675 | __r._M_ptr = 0; | |
676 | } | |
aaf0ca6f | 677 | |
c8bd30dd PC |
678 | /** @brief Constructs a %__shared_ptr that shares ownership with @a __r |
679 | * and stores a copy of the pointer stored in @a __r. | |
680 | * @param __r A weak_ptr. | |
681 | * @post use_count() == __r.use_count() | |
682 | * @throw bad_weak_ptr when __r.expired(), | |
459f9f82 PC |
683 | * in which case the constructor has no effect. |
684 | */ | |
685 | template<typename _Tp1> | |
686 | explicit | |
687 | __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r) | |
688 | : _M_refcount(__r._M_refcount) // may throw | |
689 | { | |
690 | __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) | |
c8bd30dd | 691 | // It is now safe to copy __r._M_ptr, as _M_refcount(__r._M_refcount) |
459f9f82 PC |
692 | // did not throw. |
693 | _M_ptr = __r._M_ptr; | |
694 | } | |
81daf4ba | 695 | |
640cbe76 JW |
696 | template<typename _Tp1, typename _Del> |
697 | explicit | |
698 | __shared_ptr(const std::unique_ptr<_Tp1, _Del>&) = delete; | |
699 | ||
459f9f82 | 700 | /** |
640cbe76 | 701 | * If an exception is thrown this constructor has no effect. |
459f9f82 | 702 | */ |
640cbe76 | 703 | template<typename _Tp1, typename _Del> |
459f9f82 | 704 | explicit |
640cbe76 | 705 | __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) |
459f9f82 PC |
706 | : _M_ptr(__r.get()), _M_refcount() |
707 | { | |
aaf0ca6f | 708 | __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) |
c8bd30dd | 709 | _Tp1* __tmp = __r.get(); |
640cbe76 | 710 | _M_refcount = __shared_count<_Lp>(std::move(__r)); |
c8bd30dd | 711 | __enable_shared_from_this_helper(_M_refcount, __tmp, __tmp); |
459f9f82 | 712 | } |
459f9f82 | 713 | |
640cbe76 JW |
714 | #if _GLIBCXX_DEPRECATED |
715 | /** | |
716 | * @post use_count() == 1 and __r.get() == 0 | |
717 | */ | |
459f9f82 | 718 | template<typename _Tp1> |
640cbe76 JW |
719 | explicit |
720 | __shared_ptr(std::auto_ptr<_Tp1>&& __r) | |
721 | : _M_ptr(__r.get()), _M_refcount() | |
459f9f82 | 722 | { |
640cbe76 JW |
723 | __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) |
724 | // TODO requires _Tp1 is complete, delete __r.release() well-formed | |
725 | _Tp1* __tmp = __r.get(); | |
726 | _M_refcount = __shared_count<_Lp>(std::move(__r)); | |
727 | __enable_shared_from_this_helper(_M_refcount, __tmp, __tmp); | |
459f9f82 | 728 | } |
aaf0ca6f | 729 | #endif |
640cbe76 | 730 | |
459f9f82 PC |
731 | template<typename _Tp1> |
732 | __shared_ptr& | |
733 | operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws | |
734 | { | |
735 | _M_ptr = __r._M_ptr; | |
c8bd30dd | 736 | _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw |
459f9f82 PC |
737 | return *this; |
738 | } | |
b758b22a | 739 | |
640cbe76 | 740 | #if _GLIBCXX_DEPRECATED |
459f9f82 PC |
741 | template<typename _Tp1> |
742 | __shared_ptr& | |
640cbe76 | 743 | operator=(std::auto_ptr<_Tp1>&& __r) |
459f9f82 | 744 | { |
640cbe76 | 745 | __shared_ptr(std::move(__r)).swap(*this); |
459f9f82 PC |
746 | return *this; |
747 | } | |
40abbf1f | 748 | #endif |
b758b22a | 749 | |
aaf0ca6f JW |
750 | __shared_ptr& |
751 | operator=(__shared_ptr&& __r) | |
752 | { | |
753 | __shared_ptr(std::move(__r)).swap(*this); | |
754 | return *this; | |
755 | } | |
756 | ||
757 | template<class _Tp1> | |
758 | __shared_ptr& | |
759 | operator=(__shared_ptr<_Tp1, _Lp>&& __r) | |
760 | { | |
761 | __shared_ptr(std::move(__r)).swap(*this); | |
762 | return *this; | |
763 | } | |
640cbe76 JW |
764 | |
765 | template<typename _Tp1, typename _Del> | |
766 | __shared_ptr& | |
767 | operator=(const std::unique_ptr<_Tp1, _Del>& __r) = delete; | |
768 | ||
769 | template<typename _Tp1, typename _Del> | |
770 | __shared_ptr& | |
771 | operator=(std::unique_ptr<_Tp1, _Del>&& __r) | |
772 | { | |
773 | __shared_ptr(std::move(__r)).swap(*this); | |
774 | return *this; | |
775 | } | |
aaf0ca6f | 776 | |
459f9f82 PC |
777 | void |
778 | reset() // never throws | |
779 | { __shared_ptr().swap(*this); } | |
b758b22a | 780 | |
459f9f82 PC |
781 | template<typename _Tp1> |
782 | void | |
783 | reset(_Tp1* __p) // _Tp1 must be complete. | |
784 | { | |
785 | // Catch self-reset errors. | |
786 | _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr); | |
787 | __shared_ptr(__p).swap(*this); | |
788 | } | |
b758b22a | 789 | |
459f9f82 PC |
790 | template<typename _Tp1, typename _Deleter> |
791 | void | |
c8bd30dd | 792 | reset(_Tp1* __p, _Deleter __d) |
459f9f82 | 793 | { __shared_ptr(__p, __d).swap(*this); } |
b758b22a | 794 | |
aaf0ca6f JW |
795 | template<typename _Tp1, typename _Deleter, typename _Alloc> |
796 | void | |
797 | reset(_Tp1* __p, _Deleter __d, const _Alloc& __a) | |
798 | { __shared_ptr(__p, __d, __a).swap(*this); } | |
799 | ||
800 | // Allow class instantiation when _Tp is [cv-qual] void. | |
4a27a739 | 801 | typename std::add_lvalue_reference<_Tp>::type |
459f9f82 | 802 | operator*() const // never throws |
b758b22a | 803 | { |
459f9f82 PC |
804 | _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0); |
805 | return *_M_ptr; | |
b758b22a BK |
806 | } |
807 | ||
459f9f82 PC |
808 | _Tp* |
809 | operator->() const // never throws | |
b758b22a | 810 | { |
459f9f82 PC |
811 | _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0); |
812 | return _M_ptr; | |
b758b22a | 813 | } |
459f9f82 PC |
814 | |
815 | _Tp* | |
816 | get() const // never throws | |
817 | { return _M_ptr; } | |
b758b22a | 818 | |
d29d4507 BK |
819 | explicit operator bool() const // never throws |
820 | { return _M_ptr == 0 ? false : true; } | |
b758b22a | 821 | |
459f9f82 PC |
822 | bool |
823 | unique() const // never throws | |
c8bd30dd | 824 | { return _M_refcount._M_unique(); } |
459f9f82 PC |
825 | |
826 | long | |
827 | use_count() const // never throws | |
c8bd30dd | 828 | { return _M_refcount._M_get_use_count(); } |
b758b22a | 829 | |
b758b22a | 830 | void |
2ea25939 | 831 | swap(__shared_ptr<_Tp, _Lp>& __other) // never throws |
b758b22a | 832 | { |
459f9f82 | 833 | std::swap(_M_ptr, __other._M_ptr); |
c8bd30dd | 834 | _M_refcount._M_swap(__other._M_refcount); |
b758b22a BK |
835 | } |
836 | ||
8dd5e93a JW |
837 | template<typename _Tp1> |
838 | bool | |
839 | owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const | |
840 | { return _M_refcount._M_less(__rhs._M_refcount); } | |
841 | ||
842 | template<typename _Tp1> | |
843 | bool | |
844 | owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const | |
845 | { return _M_refcount._M_less(__rhs._M_refcount); } | |
846 | ||
aaf0ca6f JW |
847 | protected: |
848 | // This constructor is non-standard, it is used by allocate_shared. | |
849 | template<typename _Alloc, typename... _Args> | |
850 | __shared_ptr(_Sp_make_shared_tag __tag, _Alloc __a, _Args&&... __args) | |
08df5d3e PC |
851 | : _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a, |
852 | std::forward<_Args>(__args)...) | |
aaf0ca6f JW |
853 | { |
854 | // _M_ptr needs to point to the newly constructed object. | |
855 | // This relies on _Sp_counted_ptr_inplace::_M_get_deleter. | |
08df5d3e | 856 | void* __p = _M_refcount._M_get_deleter(typeid(__tag)); |
aaf0ca6f | 857 | _M_ptr = static_cast<_Tp*>(__p); |
08df5d3e | 858 | __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr); |
aaf0ca6f JW |
859 | } |
860 | ||
861 | template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc, | |
862 | typename... _Args> | |
863 | friend __shared_ptr<_Tp1, _Lp1> | |
864 | __allocate_shared(_Alloc __a, _Args&&... __args); | |
aaf0ca6f | 865 | |
459f9f82 PC |
866 | private: |
867 | void* | |
868 | _M_get_deleter(const std::type_info& __ti) const | |
c8bd30dd | 869 | { return _M_refcount._M_get_deleter(__ti); } |
459f9f82 | 870 | |
459f9f82 PC |
871 | template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr; |
872 | template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr; | |
873 | ||
874 | template<typename _Del, typename _Tp1, _Lock_policy _Lp1> | |
875 | friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&); | |
876 | ||
c8bd30dd PC |
877 | _Tp* _M_ptr; // Contained pointer. |
878 | __shared_count<_Lp> _M_refcount; // Reference counter. | |
459f9f82 PC |
879 | }; |
880 | ||
8dd5e93a JW |
881 | // 20.8.13.2.7 shared_ptr comparisons |
882 | template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> | |
883 | inline bool | |
884 | operator==(const __shared_ptr<_Tp1, _Lp>& __a, | |
885 | const __shared_ptr<_Tp2, _Lp>& __b) | |
886 | { return __a.get() == __b.get(); } | |
887 | ||
888 | template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> | |
889 | inline bool | |
890 | operator!=(const __shared_ptr<_Tp1, _Lp>& __a, | |
891 | const __shared_ptr<_Tp2, _Lp>& __b) | |
892 | { return __a.get() != __b.get(); } | |
893 | ||
894 | template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> | |
895 | inline bool | |
896 | operator<(const __shared_ptr<_Tp1, _Lp>& __a, | |
897 | const __shared_ptr<_Tp2, _Lp>& __b) | |
898 | { return __a.get() < __b.get(); } | |
899 | ||
900 | template<typename _Sp> | |
901 | struct _Sp_less : public binary_function<_Sp, _Sp, bool> | |
902 | { | |
903 | bool | |
904 | operator()(const _Sp& __lhs, const _Sp& __rhs) const | |
905 | { | |
906 | return std::less<typename _Sp::element_type*>()(__lhs.get(), | |
907 | __rhs.get()); | |
908 | } | |
909 | }; | |
910 | ||
911 | template<typename _Tp, _Lock_policy _Lp> | |
912 | struct less<__shared_ptr<_Tp, _Lp>> | |
913 | : public _Sp_less<__shared_ptr<_Tp, _Lp>> | |
914 | { }; | |
915 | ||
916 | // XXX LessThanComparable<_Tp> concept should provide >, >= and <= | |
917 | template<typename _Tp, _Lock_policy _Lp> | |
918 | inline bool | |
919 | operator>(const __shared_ptr<_Tp, _Lp>& __a, | |
920 | const __shared_ptr<_Tp, _Lp>& __b) | |
921 | { return __a.get() > __b.get(); } | |
922 | ||
923 | template<typename _Tp, _Lock_policy _Lp> | |
924 | inline bool | |
925 | operator>=(const __shared_ptr<_Tp, _Lp>& __a, | |
926 | const __shared_ptr<_Tp, _Lp>& __b) | |
927 | { return __a.get() >= __b.get(); } | |
928 | ||
929 | template<typename _Tp, _Lock_policy _Lp> | |
930 | inline bool | |
931 | operator<=(const __shared_ptr<_Tp, _Lp>& __a, | |
932 | const __shared_ptr<_Tp, _Lp>& __b) | |
933 | { return __a.get() <= __b.get(); } | |
934 | ||
459f9f82 PC |
935 | // 2.2.3.8 shared_ptr specialized algorithms. |
936 | template<typename _Tp, _Lock_policy _Lp> | |
937 | inline void | |
938 | swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) | |
939 | { __a.swap(__b); } | |
940 | ||
941 | // 2.2.3.9 shared_ptr casts | |
942 | /** @warning The seemingly equivalent | |
c8bd30dd | 943 | * <code>shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))</code> |
459f9f82 PC |
944 | * will eventually result in undefined behaviour, |
945 | * attempting to delete the same object twice. | |
946 | */ | |
947 | template<typename _Tp, typename _Tp1, _Lock_policy _Lp> | |
aaf0ca6f | 948 | inline __shared_ptr<_Tp, _Lp> |
459f9f82 | 949 | static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) |
640cbe76 | 950 | { return __shared_ptr<_Tp, _Lp>(__r, static_cast<_Tp*>(__r.get())); } |
459f9f82 PC |
951 | |
952 | /** @warning The seemingly equivalent | |
c8bd30dd | 953 | * <code>shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))</code> |
459f9f82 PC |
954 | * will eventually result in undefined behaviour, |
955 | * attempting to delete the same object twice. | |
956 | */ | |
957 | template<typename _Tp, typename _Tp1, _Lock_policy _Lp> | |
aaf0ca6f | 958 | inline __shared_ptr<_Tp, _Lp> |
459f9f82 | 959 | const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) |
640cbe76 | 960 | { return __shared_ptr<_Tp, _Lp>(__r, const_cast<_Tp*>(__r.get())); } |
459f9f82 PC |
961 | |
962 | /** @warning The seemingly equivalent | |
c8bd30dd | 963 | * <code>shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))</code> |
459f9f82 PC |
964 | * will eventually result in undefined behaviour, |
965 | * attempting to delete the same object twice. | |
966 | */ | |
967 | template<typename _Tp, typename _Tp1, _Lock_policy _Lp> | |
aaf0ca6f | 968 | inline __shared_ptr<_Tp, _Lp> |
459f9f82 | 969 | dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) |
aaf0ca6f | 970 | { |
aaf0ca6f JW |
971 | if (_Tp* __p = dynamic_cast<_Tp*>(__r.get())) |
972 | return __shared_ptr<_Tp, _Lp>(__r, __p); | |
973 | return __shared_ptr<_Tp, _Lp>(); | |
aaf0ca6f | 974 | } |
459f9f82 PC |
975 | |
976 | // 2.2.3.7 shared_ptr I/O | |
977 | template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp> | |
978 | std::basic_ostream<_Ch, _Tr>& | |
979 | operator<<(std::basic_ostream<_Ch, _Tr>& __os, | |
980 | const __shared_ptr<_Tp, _Lp>& __p) | |
b758b22a | 981 | { |
459f9f82 PC |
982 | __os << __p.get(); |
983 | return __os; | |
b758b22a | 984 | } |
b758b22a | 985 | |
459f9f82 PC |
986 | // 2.2.3.10 shared_ptr get_deleter (experimental) |
987 | template<typename _Del, typename _Tp, _Lock_policy _Lp> | |
988 | inline _Del* | |
989 | get_deleter(const __shared_ptr<_Tp, _Lp>& __p) | |
990 | { return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del))); } | |
b758b22a | 991 | |
b758b22a | 992 | |
459f9f82 PC |
993 | template<typename _Tp, _Lock_policy _Lp> |
994 | class __weak_ptr | |
b758b22a | 995 | { |
459f9f82 PC |
996 | public: |
997 | typedef _Tp element_type; | |
998 | ||
c8bd30dd PC |
999 | __weak_ptr() |
1000 | : _M_ptr(0), _M_refcount() // never throws | |
459f9f82 | 1001 | { } |
b758b22a | 1002 | |
459f9f82 PC |
1003 | // Generated copy constructor, assignment, destructor are fine. |
1004 | ||
1005 | // The "obvious" converting constructor implementation: | |
1006 | // | |
c8bd30dd PC |
1007 | // template<typename _Tp1> |
1008 | // __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) | |
1009 | // : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws | |
459f9f82 PC |
1010 | // { } |
1011 | // | |
1012 | // has a serious problem. | |
1013 | // | |
c8bd30dd PC |
1014 | // __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr) |
1015 | // conversion may require access to *__r._M_ptr (virtual inheritance). | |
459f9f82 PC |
1016 | // |
1017 | // It is not possible to avoid spurious access violations since | |
c8bd30dd | 1018 | // in multithreaded programs __r._M_ptr may be invalidated at any point. |
459f9f82 | 1019 | template<typename _Tp1> |
dcd400b5 PC |
1020 | __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) |
1021 | : _M_refcount(__r._M_refcount) // never throws | |
459f9f82 PC |
1022 | { |
1023 | __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) | |
c8bd30dd | 1024 | _M_ptr = __r.lock().get(); |
459f9f82 | 1025 | } |
b758b22a | 1026 | |
459f9f82 | 1027 | template<typename _Tp1> |
dcd400b5 PC |
1028 | __weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r) |
1029 | : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws | |
459f9f82 | 1030 | { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) } |
b758b22a | 1031 | |
459f9f82 PC |
1032 | template<typename _Tp1> |
1033 | __weak_ptr& | |
dcd400b5 | 1034 | operator=(const __weak_ptr<_Tp1, _Lp>& __r) // never throws |
459f9f82 | 1035 | { |
dcd400b5 PC |
1036 | _M_ptr = __r.lock().get(); |
1037 | _M_refcount = __r._M_refcount; | |
459f9f82 PC |
1038 | return *this; |
1039 | } | |
1040 | ||
1041 | template<typename _Tp1> | |
1042 | __weak_ptr& | |
dcd400b5 | 1043 | operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws |
459f9f82 | 1044 | { |
dcd400b5 PC |
1045 | _M_ptr = __r._M_ptr; |
1046 | _M_refcount = __r._M_refcount; | |
459f9f82 PC |
1047 | return *this; |
1048 | } | |
b758b22a | 1049 | |
459f9f82 PC |
1050 | __shared_ptr<_Tp, _Lp> |
1051 | lock() const // never throws | |
b758b22a | 1052 | { |
b758b22a | 1053 | #ifdef __GTHREADS |
459f9f82 PC |
1054 | // Optimization: avoid throw overhead. |
1055 | if (expired()) | |
1056 | return __shared_ptr<element_type, _Lp>(); | |
c8bd30dd | 1057 | |
bc2631e0 | 1058 | __try |
459f9f82 PC |
1059 | { |
1060 | return __shared_ptr<element_type, _Lp>(*this); | |
1061 | } | |
bc2631e0 | 1062 | __catch(const bad_weak_ptr&) |
459f9f82 PC |
1063 | { |
1064 | // Q: How can we get here? | |
1065 | // A: Another thread may have invalidated r after the | |
1066 | // use_count test above. | |
e31fc6a5 | 1067 | return __shared_ptr<element_type, _Lp>(); |
459f9f82 PC |
1068 | } |
1069 | ||
b758b22a | 1070 | #else |
459f9f82 PC |
1071 | // Optimization: avoid try/catch overhead when single threaded. |
1072 | return expired() ? __shared_ptr<element_type, _Lp>() | |
1073 | : __shared_ptr<element_type, _Lp>(*this); | |
b758b22a BK |
1074 | |
1075 | #endif | |
459f9f82 | 1076 | } // XXX MT |
b758b22a | 1077 | |
459f9f82 PC |
1078 | long |
1079 | use_count() const // never throws | |
c8bd30dd | 1080 | { return _M_refcount._M_get_use_count(); } |
b758b22a | 1081 | |
b758b22a | 1082 | bool |
459f9f82 | 1083 | expired() const // never throws |
c8bd30dd | 1084 | { return _M_refcount._M_get_use_count() == 0; } |
8dd5e93a JW |
1085 | |
1086 | template<typename _Tp1> | |
1087 | bool | |
1088 | owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const | |
1089 | { return _M_refcount._M_less(__rhs._M_refcount); } | |
1090 | ||
1091 | template<typename _Tp1> | |
1092 | bool | |
1093 | owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const | |
1094 | { return _M_refcount._M_less(__rhs._M_refcount); } | |
1095 | ||
459f9f82 PC |
1096 | void |
1097 | reset() // never throws | |
1098 | { __weak_ptr().swap(*this); } | |
77633f4c | 1099 | |
459f9f82 PC |
1100 | void |
1101 | swap(__weak_ptr& __s) // never throws | |
1102 | { | |
1103 | std::swap(_M_ptr, __s._M_ptr); | |
c8bd30dd | 1104 | _M_refcount._M_swap(__s._M_refcount); |
459f9f82 | 1105 | } |
b758b22a | 1106 | |
8dd5e93a JW |
1107 | // comparisons |
1108 | template<typename _Tp1> | |
1109 | bool operator<(const __weak_ptr<_Tp1, _Lp>&) const = delete; | |
1110 | template<typename _Tp1> | |
1111 | bool operator<=(const __weak_ptr<_Tp1, _Lp>&) const = delete; | |
1112 | template<typename _Tp1> | |
1113 | bool operator>(const __weak_ptr<_Tp1, _Lp>&) const = delete; | |
1114 | template<typename _Tp1> | |
1115 | bool operator>=(const __weak_ptr<_Tp1, _Lp>&) const = delete; | |
1116 | ||
459f9f82 | 1117 | private: |
459f9f82 PC |
1118 | // Used by __enable_shared_from_this. |
1119 | void | |
c8bd30dd | 1120 | _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) |
459f9f82 PC |
1121 | { |
1122 | _M_ptr = __ptr; | |
1123 | _M_refcount = __refcount; | |
1124 | } | |
b758b22a | 1125 | |
c8bd30dd PC |
1126 | template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr; |
1127 | template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr; | |
1128 | friend class __enable_shared_from_this<_Tp, _Lp>; | |
1129 | friend class enable_shared_from_this<_Tp>; | |
1130 | ||
c8bd30dd PC |
1131 | _Tp* _M_ptr; // Contained pointer. |
1132 | __weak_count<_Lp> _M_refcount; // Reference counter. | |
459f9f82 | 1133 | }; |
b758b22a | 1134 | |
8dd5e93a | 1135 | // 20.8.13.3.7 weak_ptr specialized algorithms. |
459f9f82 | 1136 | template<typename _Tp, _Lock_policy _Lp> |
c8bd30dd | 1137 | inline void |
459f9f82 PC |
1138 | swap(__weak_ptr<_Tp, _Lp>& __a, __weak_ptr<_Tp, _Lp>& __b) |
1139 | { __a.swap(__b); } | |
b758b22a | 1140 | |
8dd5e93a JW |
1141 | /// owner_less |
1142 | template<typename _Tp> struct owner_less; | |
1143 | ||
1144 | template<typename _Tp, typename _Tp1> | |
1145 | struct _Sp_owner_less : public binary_function<_Tp, _Tp, bool> | |
1146 | { | |
1147 | bool | |
1148 | operator()(const _Tp& __lhs, const _Tp& __rhs) const | |
1149 | { return __lhs.owner_before(__rhs); } | |
1150 | bool | |
1151 | operator()(const _Tp& __lhs, const _Tp1& __rhs) const | |
1152 | { return __lhs.owner_before(__rhs); } | |
1153 | bool | |
1154 | operator()(const _Tp1& __lhs, const _Tp& __rhs) const | |
1155 | { return __lhs.owner_before(__rhs); } | |
1156 | }; | |
1157 | ||
1158 | template<typename _Tp, _Lock_policy _Lp> | |
1159 | struct owner_less<__shared_ptr<_Tp, _Lp>> | |
1160 | : public _Sp_owner_less<__shared_ptr<_Tp, _Lp>, __weak_ptr<_Tp, _Lp>> | |
1161 | { }; | |
1162 | ||
1163 | template<typename _Tp, _Lock_policy _Lp> | |
1164 | struct owner_less<__weak_ptr<_Tp, _Lp>> | |
1165 | : public _Sp_owner_less<__weak_ptr<_Tp, _Lp>, __shared_ptr<_Tp, _Lp>> | |
1166 | { | |
1167 | }; | |
1168 | ||
b758b22a | 1169 | |
c8bd30dd | 1170 | template<typename _Tp, _Lock_policy _Lp> |
459f9f82 | 1171 | class __enable_shared_from_this |
b758b22a | 1172 | { |
459f9f82 PC |
1173 | protected: |
1174 | __enable_shared_from_this() { } | |
1175 | ||
1176 | __enable_shared_from_this(const __enable_shared_from_this&) { } | |
1177 | ||
1178 | __enable_shared_from_this& | |
1179 | operator=(const __enable_shared_from_this&) | |
1180 | { return *this; } | |
b758b22a | 1181 | |
459f9f82 PC |
1182 | ~__enable_shared_from_this() { } |
1183 | ||
1184 | public: | |
1185 | __shared_ptr<_Tp, _Lp> | |
1186 | shared_from_this() | |
c8bd30dd PC |
1187 | { return __shared_ptr<_Tp, _Lp>(this->_M_weak_this); } |
1188 | ||
459f9f82 PC |
1189 | __shared_ptr<const _Tp, _Lp> |
1190 | shared_from_this() const | |
c8bd30dd PC |
1191 | { return __shared_ptr<const _Tp, _Lp>(this->_M_weak_this); } |
1192 | ||
459f9f82 PC |
1193 | private: |
1194 | template<typename _Tp1> | |
1195 | void | |
c8bd30dd | 1196 | _M_weak_assign(_Tp1* __p, const __shared_count<_Lp>& __n) const |
459f9f82 PC |
1197 | { _M_weak_this._M_assign(__p, __n); } |
1198 | ||
1199 | template<typename _Tp1> | |
1200 | friend void | |
c8bd30dd | 1201 | __enable_shared_from_this_helper(const __shared_count<_Lp>& __pn, |
459f9f82 PC |
1202 | const __enable_shared_from_this* __pe, |
1203 | const _Tp1* __px) | |
1204 | { | |
1205 | if (__pe != 0) | |
1206 | __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn); | |
1207 | } | |
a25ce4db | 1208 | |
c8bd30dd | 1209 | mutable __weak_ptr<_Tp, _Lp> _M_weak_this; |
459f9f82 | 1210 | }; |
a25ce4db | 1211 | |
5b9daa7e BK |
1212 | /** |
1213 | * @brief A smart pointer with reference-counted copy semantics. | |
1214 | * | |
1215 | * The object pointed to is deleted when the last shared_ptr pointing to | |
1216 | * it is destroyed or reset. | |
1217 | */ | |
459f9f82 | 1218 | template<typename _Tp> |
c8bd30dd PC |
1219 | class shared_ptr |
1220 | : public __shared_ptr<_Tp> | |
459f9f82 PC |
1221 | { |
1222 | public: | |
c8bd30dd PC |
1223 | shared_ptr() |
1224 | : __shared_ptr<_Tp>() { } | |
1225 | ||
459f9f82 PC |
1226 | template<typename _Tp1> |
1227 | explicit | |
1228 | shared_ptr(_Tp1* __p) | |
1229 | : __shared_ptr<_Tp>(__p) { } | |
c8bd30dd | 1230 | |
459f9f82 PC |
1231 | template<typename _Tp1, typename _Deleter> |
1232 | shared_ptr(_Tp1* __p, _Deleter __d) | |
1233 | : __shared_ptr<_Tp>(__p, __d) { } | |
c8bd30dd | 1234 | |
aaf0ca6f JW |
1235 | template<typename _Tp1, typename _Deleter, typename _Alloc> |
1236 | shared_ptr(_Tp1* __p, _Deleter __d, const _Alloc& __a) | |
1237 | : __shared_ptr<_Tp>(__p, __d, __a) { } | |
1238 | ||
1239 | // Aliasing constructor | |
1240 | template<typename _Tp1> | |
1241 | shared_ptr(const shared_ptr<_Tp1>& __r, _Tp* __p) | |
1242 | : __shared_ptr<_Tp>(__r, __p) { } | |
aaf0ca6f | 1243 | |
459f9f82 | 1244 | template<typename _Tp1> |
c8bd30dd | 1245 | shared_ptr(const shared_ptr<_Tp1>& __r) |
459f9f82 | 1246 | : __shared_ptr<_Tp>(__r) { } |
c8bd30dd | 1247 | |
aaf0ca6f JW |
1248 | shared_ptr(shared_ptr&& __r) |
1249 | : __shared_ptr<_Tp>(std::move(__r)) { } | |
1250 | ||
1251 | template<typename _Tp1> | |
1252 | shared_ptr(shared_ptr<_Tp1>&& __r) | |
1253 | : __shared_ptr<_Tp>(std::move(__r)) { } | |
aaf0ca6f | 1254 | |
459f9f82 PC |
1255 | template<typename _Tp1> |
1256 | explicit | |
c8bd30dd | 1257 | shared_ptr(const weak_ptr<_Tp1>& __r) |
459f9f82 | 1258 | : __shared_ptr<_Tp>(__r) { } |
c8bd30dd | 1259 | |
640cbe76 | 1260 | #if _GLIBCXX_DEPRECATED |
459f9f82 PC |
1261 | template<typename _Tp1> |
1262 | explicit | |
640cbe76 JW |
1263 | shared_ptr(std::auto_ptr<_Tp1>&& __r) |
1264 | : __shared_ptr<_Tp>(std::move(__r)) { } | |
40abbf1f | 1265 | #endif |
459f9f82 | 1266 | |
640cbe76 JW |
1267 | template<typename _Tp1, typename _Del> |
1268 | explicit | |
1269 | shared_ptr(const std::unique_ptr<_Tp1, _Del>&) = delete; | |
c8bd30dd | 1270 | |
640cbe76 JW |
1271 | template<typename _Tp1, typename _Del> |
1272 | explicit | |
1273 | shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) | |
1274 | : __shared_ptr<_Tp>(std::move(__r)) { } | |
459f9f82 | 1275 | |
459f9f82 PC |
1276 | template<typename _Tp1> |
1277 | shared_ptr& | |
c8bd30dd | 1278 | operator=(const shared_ptr<_Tp1>& __r) // never throws |
459f9f82 PC |
1279 | { |
1280 | this->__shared_ptr<_Tp>::operator=(__r); | |
1281 | return *this; | |
1282 | } | |
a25ce4db | 1283 | |
640cbe76 | 1284 | #if _GLIBCXX_DEPRECATED |
459f9f82 PC |
1285 | template<typename _Tp1> |
1286 | shared_ptr& | |
640cbe76 | 1287 | operator=(std::auto_ptr<_Tp1>&& __r) |
459f9f82 | 1288 | { |
640cbe76 | 1289 | this->__shared_ptr<_Tp>::operator=(std::move(__r)); |
459f9f82 PC |
1290 | return *this; |
1291 | } | |
40abbf1f | 1292 | #endif |
aaf0ca6f | 1293 | |
aaf0ca6f JW |
1294 | shared_ptr& |
1295 | operator=(shared_ptr&& __r) | |
1296 | { | |
1297 | this->__shared_ptr<_Tp>::operator=(std::move(__r)); | |
1298 | return *this; | |
1299 | } | |
1300 | ||
1301 | template<class _Tp1> | |
1302 | shared_ptr& | |
1303 | operator=(shared_ptr<_Tp1>&& __r) | |
1304 | { | |
1305 | this->__shared_ptr<_Tp>::operator=(std::move(__r)); | |
1306 | return *this; | |
1307 | } | |
aaf0ca6f | 1308 | |
640cbe76 JW |
1309 | template<typename _Tp1, typename _Del> |
1310 | shared_ptr& | |
1311 | operator=(const std::unique_ptr<_Tp1, _Del>& __r) = delete; | |
1312 | ||
1313 | template<typename _Tp1, typename _Del> | |
1314 | shared_ptr& | |
1315 | operator=(std::unique_ptr<_Tp1, _Del>&& __r) | |
1316 | { | |
1317 | this->__shared_ptr<_Tp>::operator=(std::move(__r)); | |
1318 | return *this; | |
1319 | } | |
1320 | ||
aaf0ca6f JW |
1321 | private: |
1322 | // This constructor is non-standard, it is used by allocate_shared. | |
1323 | template<typename _Alloc, typename... _Args> | |
1324 | shared_ptr(_Sp_make_shared_tag __tag, _Alloc __a, _Args&&... __args) | |
1325 | : __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...) | |
1326 | { } | |
1327 | ||
1328 | template<typename _Tp1, typename _Alloc, typename... _Args> | |
1329 | friend shared_ptr<_Tp1> | |
1330 | allocate_shared(_Alloc __a, _Args&&... __args); | |
459f9f82 | 1331 | }; |
b758b22a | 1332 | |
8dd5e93a JW |
1333 | // 20.8.13.2.7 shared_ptr comparisons |
1334 | template<typename _Tp1, typename _Tp2> | |
1335 | inline bool | |
1336 | operator==(const shared_ptr<_Tp1>& __a, const shared_ptr<_Tp2>& __b) | |
1337 | { return __a.get() == __b.get(); } | |
1338 | ||
1339 | template<typename _Tp1, typename _Tp2> | |
1340 | inline bool | |
1341 | operator!=(const shared_ptr<_Tp1>& __a, const shared_ptr<_Tp2>& __b) | |
1342 | { return __a.get() != __b.get(); } | |
1343 | ||
1344 | template<typename _Tp1, typename _Tp2> | |
1345 | inline bool | |
1346 | operator<(const shared_ptr<_Tp1>& __a, const shared_ptr<_Tp2>& __b) | |
1347 | { return __a.get() < __b.get(); } | |
1348 | ||
1349 | template<typename _Tp> | |
1350 | struct less<shared_ptr<_Tp>> | |
1351 | : public _Sp_less<shared_ptr<_Tp>> | |
1352 | { }; | |
1353 | ||
1354 | // 20.8.13.2.9 shared_ptr specialized algorithms. | |
640cbe76 JW |
1355 | template<typename _Tp> |
1356 | inline void | |
8dd5e93a | 1357 | swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) |
640cbe76 JW |
1358 | { __a.swap(__b); } |
1359 | ||
8dd5e93a | 1360 | // 20.8.13.2.10 shared_ptr casts. |
c8bd30dd | 1361 | template<typename _Tp, typename _Tp1> |
aaf0ca6f | 1362 | inline shared_ptr<_Tp> |
c8bd30dd | 1363 | static_pointer_cast(const shared_ptr<_Tp1>& __r) |
640cbe76 | 1364 | { return shared_ptr<_Tp>(__r, static_cast<_Tp*>(__r.get())); } |
c8bd30dd PC |
1365 | |
1366 | template<typename _Tp, typename _Tp1> | |
aaf0ca6f | 1367 | inline shared_ptr<_Tp> |
c8bd30dd | 1368 | const_pointer_cast(const shared_ptr<_Tp1>& __r) |
640cbe76 | 1369 | { return shared_ptr<_Tp>(__r, const_cast<_Tp*>(__r.get())); } |
c8bd30dd PC |
1370 | |
1371 | template<typename _Tp, typename _Tp1> | |
aaf0ca6f | 1372 | inline shared_ptr<_Tp> |
c8bd30dd | 1373 | dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) |
aaf0ca6f | 1374 | { |
aaf0ca6f JW |
1375 | if (_Tp* __p = dynamic_cast<_Tp*>(__r.get())) |
1376 | return shared_ptr<_Tp>(__r, __p); | |
1377 | return shared_ptr<_Tp>(); | |
aaf0ca6f | 1378 | } |
c8bd30dd PC |
1379 | |
1380 | ||
5b9daa7e BK |
1381 | /** |
1382 | * @brief A smart pointer with weak semantics. | |
1383 | * | |
1384 | * With forwarding constructors and assignment operators. | |
1385 | */ | |
c8bd30dd PC |
1386 | template<typename _Tp> |
1387 | class weak_ptr | |
1388 | : public __weak_ptr<_Tp> | |
1389 | { | |
1390 | public: | |
1391 | weak_ptr() | |
1392 | : __weak_ptr<_Tp>() { } | |
1393 | ||
1394 | template<typename _Tp1> | |
1395 | weak_ptr(const weak_ptr<_Tp1>& __r) | |
1396 | : __weak_ptr<_Tp>(__r) { } | |
1397 | ||
1398 | template<typename _Tp1> | |
1399 | weak_ptr(const shared_ptr<_Tp1>& __r) | |
1400 | : __weak_ptr<_Tp>(__r) { } | |
1401 | ||
1402 | template<typename _Tp1> | |
1403 | weak_ptr& | |
1404 | operator=(const weak_ptr<_Tp1>& __r) // never throws | |
1405 | { | |
1406 | this->__weak_ptr<_Tp>::operator=(__r); | |
1407 | return *this; | |
1408 | } | |
1409 | ||
1410 | template<typename _Tp1> | |
1411 | weak_ptr& | |
1412 | operator=(const shared_ptr<_Tp1>& __r) // never throws | |
1413 | { | |
1414 | this->__weak_ptr<_Tp>::operator=(__r); | |
1415 | return *this; | |
1416 | } | |
1417 | ||
1418 | shared_ptr<_Tp> | |
1419 | lock() const // never throws | |
1420 | { | |
1421 | #ifdef __GTHREADS | |
1422 | if (this->expired()) | |
1423 | return shared_ptr<_Tp>(); | |
1424 | ||
bc2631e0 | 1425 | __try |
c8bd30dd PC |
1426 | { |
1427 | return shared_ptr<_Tp>(*this); | |
1428 | } | |
bc2631e0 | 1429 | __catch(const bad_weak_ptr&) |
c8bd30dd PC |
1430 | { |
1431 | return shared_ptr<_Tp>(); | |
1432 | } | |
1433 | #else | |
1434 | return this->expired() ? shared_ptr<_Tp>() | |
1435 | : shared_ptr<_Tp>(*this); | |
1436 | #endif | |
1437 | } | |
8dd5e93a JW |
1438 | |
1439 | // comparisons | |
1440 | template<typename _Tp1> | |
1441 | bool operator<(const weak_ptr<_Tp1>&) const = delete; | |
1442 | template<typename _Tp1> | |
1443 | bool operator<=(const weak_ptr<_Tp1>&) const = delete; | |
1444 | template<typename _Tp1> | |
1445 | bool operator>(const weak_ptr<_Tp1>&) const = delete; | |
1446 | template<typename _Tp1> | |
1447 | bool operator>=(const weak_ptr<_Tp1>&) const = delete; | |
c8bd30dd PC |
1448 | }; |
1449 | ||
8dd5e93a JW |
1450 | // 20.8.13.3.7 weak_ptr specialized algorithms. |
1451 | template<typename _Tp> | |
1452 | inline void | |
1453 | swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) | |
1454 | { __a.swap(__b); } | |
1455 | ||
1456 | /// owner_less | |
1457 | template<typename _Tp> | |
1458 | struct owner_less<shared_ptr<_Tp>> | |
1459 | : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>> | |
1460 | { }; | |
1461 | ||
1462 | template<typename _Tp> | |
1463 | struct owner_less<weak_ptr<_Tp>> | |
1464 | : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>> | |
1465 | { }; | |
1466 | ||
5b9daa7e BK |
1467 | /** |
1468 | * @brief Base class allowing use of member function shared_from_this. | |
1469 | */ | |
459f9f82 | 1470 | template<typename _Tp> |
c8bd30dd | 1471 | class enable_shared_from_this |
459f9f82 PC |
1472 | { |
1473 | protected: | |
c8bd30dd | 1474 | enable_shared_from_this() { } |
459f9f82 | 1475 | |
c8bd30dd PC |
1476 | enable_shared_from_this(const enable_shared_from_this&) { } |
1477 | ||
1478 | enable_shared_from_this& | |
1479 | operator=(const enable_shared_from_this&) | |
1480 | { return *this; } | |
1481 | ||
1482 | ~enable_shared_from_this() { } | |
1483 | ||
1484 | public: | |
1485 | shared_ptr<_Tp> | |
1486 | shared_from_this() | |
1487 | { return shared_ptr<_Tp>(this->_M_weak_this); } | |
1488 | ||
1489 | shared_ptr<const _Tp> | |
1490 | shared_from_this() const | |
1491 | { return shared_ptr<const _Tp>(this->_M_weak_this); } | |
1492 | ||
1493 | private: | |
1494 | template<typename _Tp1> | |
1495 | void | |
1496 | _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const | |
1497 | { _M_weak_this._M_assign(__p, __n); } | |
1498 | ||
1499 | template<typename _Tp1> | |
1500 | friend void | |
1501 | __enable_shared_from_this_helper(const __shared_count<>& __pn, | |
1502 | const enable_shared_from_this* __pe, | |
1503 | const _Tp1* __px) | |
1504 | { | |
1505 | if (__pe != 0) | |
1506 | __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn); | |
1507 | } | |
1508 | ||
1509 | mutable weak_ptr<_Tp> _M_weak_this; | |
459f9f82 | 1510 | }; |
c8bd30dd | 1511 | |
aaf0ca6f JW |
1512 | template<typename _Tp, _Lock_policy _Lp, typename _Alloc, typename... _Args> |
1513 | inline __shared_ptr<_Tp, _Lp> | |
1514 | __allocate_shared(_Alloc __a, _Args&&... __args) | |
1515 | { | |
1516 | return __shared_ptr<_Tp, _Lp>(_Sp_make_shared_tag(), | |
1517 | std::forward<_Alloc>(__a), std::forward<_Args>(__args)...); | |
1518 | } | |
1519 | ||
1520 | template<typename _Tp, _Lock_policy _Lp, typename... _Args> | |
1521 | inline __shared_ptr<_Tp, _Lp> | |
1522 | __make_shared(_Args&&... __args) | |
1523 | { | |
1524 | typedef typename std::remove_const<_Tp>::type _Tp_nc; | |
1525 | return __allocate_shared<_Tp, _Lp>(std::allocator<_Tp_nc>(), | |
1526 | std::forward<_Args>(__args)...); | |
1527 | } | |
1528 | ||
5b9daa7e | 1529 | /** @brief Create an object that is owned by a shared_ptr. |
aaf0ca6f JW |
1530 | * @param __a An allocator. |
1531 | * @param __args Arguments for the @a _Tp object's constructor. | |
1532 | * @return A shared_ptr that owns the newly created object. | |
1533 | * @throw An exception thrown from @a _Alloc::allocate or from the | |
1534 | * constructor of @a _Tp. | |
1535 | * | |
1536 | * A copy of @a __a will be used to allocate memory for the shared_ptr | |
1537 | * and the new object. | |
1538 | */ | |
1539 | template<typename _Tp, typename _Alloc, typename... _Args> | |
1540 | inline shared_ptr<_Tp> | |
1541 | allocate_shared(_Alloc __a, _Args&&... __args) | |
1542 | { | |
1543 | return shared_ptr<_Tp>(_Sp_make_shared_tag(), std::forward<_Alloc>(__a), | |
1544 | std::forward<_Args>(__args)...); | |
1545 | } | |
1546 | ||
1547 | /** @brief Create an object that is owned by a shared_ptr. | |
1548 | * @param __args Arguments for the @a _Tp object's constructor. | |
1549 | * @return A shared_ptr that owns the newly created object. | |
1550 | * @throw std::bad_alloc, or an exception thrown from the | |
1551 | * constructor of @a _Tp. | |
1552 | */ | |
1553 | template<typename _Tp, typename... _Args> | |
1554 | inline shared_ptr<_Tp> | |
1555 | make_shared(_Args&&... __args) | |
1556 | { | |
1557 | typedef typename std::remove_const<_Tp>::type _Tp_nc; | |
1558 | return allocate_shared<_Tp>(std::allocator<_Tp_nc>(), | |
1559 | std::forward<_Args>(__args)...); | |
1560 | } | |
aaf0ca6f | 1561 | |
5b9daa7e BK |
1562 | // @} group pointer_abstractions |
1563 | ||
1564 | _GLIBCXX_END_NAMESPACE | |
32fdf2f4 JW |
1565 | |
1566 | #endif // _SHARED_PTR_H |