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