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