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