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