boost_shared_ptr.h

Go to the documentation of this file.
00001 // <tr1/boost_shared_ptr.h> -*- C++ -*-
00002 
00003 // Copyright (C) 2005 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 2, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // You should have received a copy of the GNU General Public License along
00017 // with this library; see the file COPYING.  If not, write to the Free
00018 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
00019 // USA.
00020 
00021 // As a special exception, you may use this file as part of a free software
00022 // library without restriction.  Specifically, if other files instantiate
00023 // templates or use macros or inline functions from this file, or you compile
00024 // this file and link it with other files to produce an executable, this
00025 // file does not by itself cause the resulting executable to be covered by
00026 // the GNU General Public License.  This exception does not however
00027 // invalidate any other reasons why the executable file might be covered by
00028 // the GNU General Public License.
00029 
00030 //  shared_count.hpp
00031 //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
00032 
00033 //  shared_ptr.hpp
00034 //  Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
00035 //  Copyright (C) 2001, 2002, 2003 Peter Dimov
00036 
00037 //  weak_ptr.hpp
00038 //  Copyright (C) 2001, 2002, 2003 Peter Dimov
00039 
00040 //  enable_shared_from_this.hpp
00041 //  Copyright (C) 2002 Peter Dimov
00042 
00043 // Distributed under the Boost Software License, Version 1.0. (See
00044 // accompanying file LICENSE_1_0.txt or copy at
00045 // http://www.boost.org/LICENSE_1_0.txt)
00046 
00047 // GCC Note:  based on version 1.32.0 of the Boost library.
00048 
00054 #ifndef _BOOST_SHARED_PTR_H
00055 #define _BOOST_SHARED_PTR_H 1
00056 
00057 // namespace std::tr1
00058 namespace std
00059 {
00060 namespace tr1
00061 {
00062 
00063 class bad_weak_ptr : public std::exception
00064 {
00065 public:
00066 
00067   virtual char const*
00068   what() const throw()
00069   { return "tr1::bad_weak_ptr"; }
00070 };
00071 
00072 // Helper for exception objects in <tr1/memory>
00073 // TODO this should be defined in a different file.
00074 inline void
00075 __throw_bad_weak_ptr()
00076 {
00077 #if __EXCEPTIONS
00078   throw bad_weak_ptr();
00079 #else
00080   std::abort();
00081 #endif
00082 }
00083 
00084 
00085 template<typename _Tp>
00086   struct _Sp_deleter
00087   {
00088     typedef void result_type;
00089     typedef _Tp* argument_type;
00090 
00091     void
00092     operator()(_Tp* p) const
00093     { delete p; }
00094   };
00095 
00096 
00097 class _Sp_counted_base
00098 {
00099 public:
00100 
00101   _Sp_counted_base()
00102   : _M_use_count(1), _M_weak_count(1)
00103   {
00104     // For the case of __GTHREAD_MUTEX_INIT we haven't initialised
00105     // the mutex yet, so do it now.
00106 #if defined(__GTHREADS) && defined(__GTHREAD_MUTEX_INIT)
00107     __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT;
00108     _M_mutex = __tmp;
00109 #endif
00110   }
00111 
00112   virtual
00113   ~_Sp_counted_base() // nothrow
00114   { }
00115 
00116   // dispose() is called when _M_use_count drops to zero, to release
00117   // the resources managed by *this.
00118   virtual void
00119   dispose() = 0; // nothrow
00120 
00121   // destroy() is called when _M_weak_count drops to zero.
00122   virtual void
00123   destroy() // nothrow
00124   {
00125     delete this;
00126   }
00127 
00128   virtual void*
00129   get_deleter(const std::type_info&) = 0;
00130 
00131   void
00132   add_ref_copy()
00133   {
00134     __gnu_cxx::__atomic_add(&_M_use_count, 1);
00135   }
00136 
00137   void
00138   add_ref_lock()
00139   {
00140     __gnu_cxx::lock lock(_M_mutex);
00141     if (__gnu_cxx::__exchange_and_add(&_M_use_count, 1) == 0)
00142       {
00143     _M_use_count = 0;
00144     __throw_bad_weak_ptr();
00145       }
00146   }
00147 
00148   void
00149   release() // nothrow
00150   {
00151     if (__gnu_cxx::__exchange_and_add(&_M_use_count, -1) == 1)
00152       {
00153     dispose();
00154 #ifdef __GTHREADS   
00155     _GLIBCXX_READ_MEM_BARRIER;
00156     _GLIBCXX_WRITE_MEM_BARRIER;
00157 #endif
00158     if (__gnu_cxx::__exchange_and_add(&_M_weak_count, -1) == 1)
00159       destroy();
00160       }
00161   }
00162 
00163   void
00164   weak_add_ref() // nothrow
00165   {
00166     __gnu_cxx::__atomic_add(&_M_weak_count, 1);
00167   }
00168 
00169   void
00170   weak_release() // nothrow
00171   {
00172     if (__gnu_cxx::__exchange_and_add(&_M_weak_count, -1) == 1)
00173       {
00174 #ifdef __GTHREADS
00175     _GLIBCXX_READ_MEM_BARRIER;
00176     _GLIBCXX_WRITE_MEM_BARRIER;
00177 #endif
00178     destroy();
00179       }
00180   }
00181 
00182   long
00183   use_count() const // nothrow
00184   {
00185     return _M_use_count;  // XXX is this MT safe?
00186   }
00187 
00188 private:
00189 
00190   _Sp_counted_base(_Sp_counted_base const&);
00191   _Sp_counted_base& operator=(_Sp_counted_base const&);
00192 
00193   _Atomic_word _M_use_count;        // #shared
00194   _Atomic_word _M_weak_count;       // #weak + (#shared != 0)
00195   __gnu_cxx::mutex_type _M_mutex;
00196 };
00197 
00198 template<typename _Ptr, typename _Deleter>
00199   class _Sp_counted_base_impl
00200   : public _Sp_counted_base
00201   {
00202   public:
00203 
00208     _Sp_counted_base_impl(_Ptr __p, _Deleter __d)
00209     : _M_ptr(__p), _M_del(__d)
00210     { }
00211     
00212     virtual void
00213     dispose() // nothrow
00214     {
00215       _M_del(_M_ptr);
00216     }
00217     
00218     virtual void*
00219     get_deleter(const std::type_info& __ti)
00220     {
00221       return __ti == typeid(_Deleter) ? &_M_del : 0;
00222     }
00223     
00224   private:
00225     _Sp_counted_base_impl(const _Sp_counted_base_impl&);
00226     _Sp_counted_base_impl& operator=(const _Sp_counted_base_impl&);
00227     
00228     _Ptr     _M_ptr; // copy constructor must not throw
00229     _Deleter _M_del; // copy constructor must not throw
00230   };
00231 
00232 class weak_count;
00233 
00234 class shared_count
00235 {
00236 private:
00237 
00238   _Sp_counted_base* _M_pi;
00239 
00240   friend class weak_count;
00241 
00242 public:
00243 
00244   shared_count()
00245   : _M_pi(0) // nothrow
00246   { }
00247 
00248   template<typename _Ptr, typename _Deleter>
00249     shared_count(_Ptr __p, _Deleter __d)
00250     : _M_pi(0)
00251     {
00252       try
00253     {
00254       _M_pi = new _Sp_counted_base_impl<_Ptr, _Deleter>(__p, __d);
00255     }
00256       catch(...)
00257     {
00258       __d(__p); // delete __p
00259       __throw_exception_again;
00260     }
00261     }
00262 
00263   // auto_ptr<_Tp> is special cased to provide the strong guarantee
00264 
00265   template<typename _Tp>
00266     explicit shared_count(std::auto_ptr<_Tp>& __r)
00267     : _M_pi(new _Sp_counted_base_impl<_Tp*,
00268         _Sp_deleter<_Tp> >(__r.get(), _Sp_deleter<_Tp>()))
00269     { __r.release(); }
00270 
00271   // throws bad_weak_ptr when __r.use_count() == 0
00272   explicit shared_count(const weak_count& __r);
00273 
00274   ~shared_count() // nothrow
00275   {
00276     if (_M_pi != 0)
00277       _M_pi->release();
00278   }
00279 
00280   shared_count(const shared_count& __r)
00281   : _M_pi(__r._M_pi) // nothrow
00282   {
00283     if (_M_pi != 0)
00284       _M_pi->add_ref_copy();
00285   }
00286 
00287   shared_count&
00288   operator=(const shared_count& __r) // nothrow
00289   {
00290     _Sp_counted_base* __tmp = __r._M_pi;
00291 
00292     if(__tmp != _M_pi)
00293       {
00294     if(__tmp != 0)
00295       __tmp->add_ref_copy();
00296     if(_M_pi != 0)
00297       _M_pi->release();
00298     _M_pi = __tmp;
00299       }
00300     return *this;
00301   }
00302 
00303   void swap(shared_count& __r) // nothrow
00304   {
00305     _Sp_counted_base* __tmp = __r._M_pi;
00306     __r._M_pi = _M_pi;
00307     _M_pi = __tmp;
00308   }
00309 
00310   long
00311   use_count() const // nothrow
00312   { return _M_pi != 0 ? _M_pi->use_count() : 0; }
00313 
00314   bool
00315   unique() const // nothrow
00316   { return this->use_count() == 1; }
00317 
00318   friend inline bool
00319   operator==(const shared_count& __a, const shared_count& __b)
00320   { return __a._M_pi == __b._M_pi; }
00321 
00322   friend inline bool
00323   operator<(const shared_count& __a, const shared_count& __b)
00324   { return std::less<_Sp_counted_base*>()(__a._M_pi, __b._M_pi); }
00325 
00326   void*
00327   get_deleter(const std::type_info& __ti) const
00328   { return _M_pi ? _M_pi->get_deleter(__ti) : 0; }
00329 };
00330 
00331 class weak_count
00332 {
00333 private:
00334 
00335   _Sp_counted_base* _M_pi;
00336 
00337   friend class shared_count;
00338 
00339 public:
00340 
00341   weak_count()
00342   : _M_pi(0) // nothrow
00343   { }
00344 
00345   weak_count(const shared_count& __r)
00346   : _M_pi(__r._M_pi) // nothrow
00347   {
00348     if (_M_pi != 0)
00349       _M_pi->weak_add_ref();
00350   }
00351 
00352   weak_count(const weak_count& __r)
00353   : _M_pi(__r._M_pi) // nothrow
00354   {
00355     if (_M_pi != 0)
00356       _M_pi->weak_add_ref();
00357   }
00358 
00359   ~weak_count() // nothrow
00360   {
00361     if (_M_pi != 0)
00362       _M_pi->weak_release();
00363   }
00364 
00365   weak_count&
00366   operator=(const shared_count& __r) // nothrow
00367   {
00368     _Sp_counted_base* __tmp = __r._M_pi;
00369     if (__tmp != 0)
00370       __tmp->weak_add_ref();
00371     if (_M_pi != 0)
00372       _M_pi->weak_release();
00373     _M_pi = __tmp;
00374 
00375     return *this;
00376   }
00377 
00378   weak_count&
00379   operator=(const weak_count& __r) // nothrow
00380   {
00381     _Sp_counted_base * __tmp = __r._M_pi;
00382     if (__tmp != 0)
00383       __tmp->weak_add_ref();
00384     if (_M_pi != 0)
00385       _M_pi->weak_release();
00386     _M_pi = __tmp;
00387 
00388     return *this;
00389   }
00390 
00391   void
00392   swap(weak_count& __r) // nothrow
00393   {
00394     _Sp_counted_base * __tmp = __r._M_pi;
00395     __r._M_pi = _M_pi;
00396     _M_pi = __tmp;
00397   }
00398 
00399   long
00400   use_count() const // nothrow
00401   { return _M_pi != 0 ? _M_pi->use_count() : 0; }
00402 
00403   friend inline bool
00404   operator==(const weak_count& __a, const weak_count& __b)
00405   { return __a._M_pi == __b._M_pi; }
00406 
00407   friend inline bool
00408   operator<(const weak_count& __a, const weak_count& __b)
00409   { return std::less<_Sp_counted_base*>()(__a._M_pi, __b._M_pi); }
00410 };
00411 
00412 inline
00413 shared_count::shared_count(const weak_count& __r)
00414 : _M_pi(__r._M_pi)
00415 {
00416   if (_M_pi != 0)
00417     _M_pi->add_ref_lock();
00418   else
00419     __throw_bad_weak_ptr();
00420 }
00421 
00422 
00423 // fwd decls
00424 template<typename _Tp>
00425   class shared_ptr;
00426 
00427 template<typename _Tp>
00428   class weak_ptr;
00429 
00430 template<typename _Tp>
00431   class enable_shared_from_this;
00432 
00433 struct __static_cast_tag {};
00434 struct __const_cast_tag {};
00435 struct __dynamic_cast_tag {};
00436 struct __polymorphic_cast_tag {};
00437 
00438 template<class _Tp>
00439   struct shared_ptr_traits
00440   { typedef _Tp& reference; };
00441 
00442 template<>
00443   struct shared_ptr_traits<void>
00444   { typedef void reference; };
00445 
00446 template<>
00447   struct shared_ptr_traits<void const>
00448   { typedef void reference; };
00449 
00450 template<>
00451   struct shared_ptr_traits<void volatile>
00452   { typedef void reference; };
00453 
00454 template<>
00455   struct shared_ptr_traits<void const volatile>
00456   { typedef void reference; };
00457 
00458 
00459 // enable_shared_from_this support
00460 
00461 // friend of enable_shared_from_this
00462 template<typename _Tp1, typename _Tp2>
00463   void
00464   __enable_shared_from_this(const shared_count& __pn,
00465                             const enable_shared_from_this<_Tp1>* __pe,
00466                             const _Tp2* __px );
00467 
00468 inline void
00469 __enable_shared_from_this(const shared_count&, ...)
00470 { }
00471 
00472 
00473 // get_deleter must be declared before friend declaration by shared_ptr.
00474 template<typename _Del, typename _Tp>
00475   _Del* get_deleter(const shared_ptr<_Tp>&);
00476 
00484 template<typename _Tp>
00485   class shared_ptr
00486   {
00487     typedef typename shared_ptr_traits<_Tp>::reference _Reference;
00488 
00489   public:
00490 
00491     typedef _Tp   element_type;
00492 
00496     shared_ptr()
00497     : _M_ptr(0), _M_refcount() // never throws
00498     { }
00499 
00505     template<typename _Tp1>
00506       explicit shared_ptr(_Tp1* __p)
00507       : _M_ptr(__p), _M_refcount(__p, _Sp_deleter<_Tp1>())
00508       {
00509         __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
00510         // __glibcxx_function_requires(_CompleteConcept<_Tp1*>)
00511 
00512         __enable_shared_from_this( _M_refcount, __p, __p );
00513       }
00514 
00515     //
00516     // Requirements: D's copy constructor and destructor must not throw
00517     //
00518     // shared_ptr will release p by calling d(p)
00519     //
00527     template<typename _Tp1, typename _Deleter>
00528       shared_ptr(_Tp1* __p, _Deleter __d)
00529       : _M_ptr(__p), _M_refcount(__p, __d)
00530       {
00531         __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
00532         // TODO requires D is CopyConstructible and d(p) well-formed
00533 
00534         __enable_shared_from_this( _M_refcount, __p, __p );
00535       }
00536 
00537     //  generated copy constructor, assignment, destructor are fine.
00538 
00545     template<typename _Tp1>
00546       shared_ptr(const shared_ptr<_Tp1>& __r)
00547       : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
00548       {
00549         __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
00550       }
00551 
00559     template<typename _Tp1>
00560       explicit shared_ptr(const weak_ptr<_Tp1>& __r)
00561       : _M_refcount(__r._M_refcount) // may throw
00562       {
00563         __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
00564         // it is now safe to copy r__._M_ptr, as _M_refcount(__r._M_refcount)
00565         // did not throw
00566         _M_ptr = __r._M_ptr;
00567       }
00568 
00572     template<typename _Tp1>
00573       explicit shared_ptr(std::auto_ptr<_Tp1>& __r)
00574       : _M_ptr(__r.get()), _M_refcount()
00575       {
00576         // TODO requires r.release() convertible to _Tp*, Tp1 is complete,
00577         // delete r.release() well-formed
00578         _Tp1 * __tmp = __r.get();
00579         _M_refcount = shared_count(__r);
00580 
00581         __enable_shared_from_this( _M_refcount, __tmp, __tmp );
00582       }
00583 
00584     template<typename _Tp1>
00585       shared_ptr(const shared_ptr<_Tp1>& __r, __static_cast_tag)
00586       : _M_ptr(static_cast<element_type*>(__r._M_ptr)),
00587     _M_refcount(__r._M_refcount)
00588       { }
00589 
00590     template<typename _Tp1>
00591       shared_ptr(const shared_ptr<_Tp1>& __r, __const_cast_tag)
00592       : _M_ptr(const_cast<element_type*>(__r._M_ptr)),
00593     _M_refcount(__r._M_refcount)
00594       { }
00595 
00596     template<typename _Tp1>
00597       shared_ptr(const shared_ptr<_Tp1>& __r, __dynamic_cast_tag)
00598       : _M_ptr(dynamic_cast<element_type*>(__r._M_ptr)),
00599     _M_refcount(__r._M_refcount)
00600       {
00601         if (_M_ptr == 0) // need to allocate new counter -- the cast failed
00602           _M_refcount = shared_count();
00603       }
00604 
00605     template<typename _Tp1>
00606       shared_ptr&
00607       operator=(const shared_ptr<_Tp1>& __r) // never throws
00608       {
00609         _M_ptr = __r._M_ptr;
00610         _M_refcount = __r._M_refcount; // shared_count::op= doesn't throw
00611         return *this;
00612       }
00613 
00614     template<typename _Tp1>
00615       shared_ptr&
00616       operator=(std::auto_ptr<_Tp1>& __r)
00617       {
00618         shared_ptr(__r).swap(*this);
00619         return *this;
00620       }
00621 
00622     void
00623     reset() // never throws
00624     { shared_ptr().swap(*this); }
00625 
00626     template<typename _Tp1>
00627       void
00628       reset(_Tp1* __p) // _Tp1 must be complete
00629       {
00630         _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr); // catch self-reset
00631                                                       // errors
00632         shared_ptr(__p).swap(*this);
00633       }
00634 
00635     template<typename _Tp1, typename _Deleter>
00636       void
00637       reset(_Tp1 * __p, _Deleter __d)
00638       { shared_ptr(__p, __d).swap(*this); }
00639 
00640     // error to instantiate if _Tp is [cv-qual] void
00641     _Reference
00642     operator*() const // never throws
00643     {
00644       _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
00645       return *_M_ptr;
00646     }
00647 
00648     _Tp*
00649     operator->() const // never throws
00650     {
00651       _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
00652       return _M_ptr;
00653     }
00654     
00655     _Tp*
00656     get() const // never throws
00657     { return _M_ptr; }
00658 
00659     // implicit conversion to "bool"
00660   private:
00661     typedef _Tp* shared_ptr::*__unspecified_bool_type;
00662 
00663   public:
00664     operator __unspecified_bool_type() const // never throws
00665     { return _M_ptr == 0 ? 0 : &shared_ptr::_M_ptr; }
00666 
00667     bool
00668     unique() const // never throws
00669     { return _M_refcount.unique(); }
00670 
00671     long
00672     use_count() const // never throws
00673     { return _M_refcount.use_count(); }
00674 
00675     void
00676     swap(shared_ptr<_Tp>& __other) // never throws
00677     {
00678       std::swap(_M_ptr, __other._M_ptr);
00679       _M_refcount.swap(__other._M_refcount);
00680     }
00681 
00682   private:
00683     void*
00684     _M_get_deleter(const std::type_info& __ti) const
00685     { return _M_refcount.get_deleter(__ti); }
00686 
00687     template<typename _Tp1>
00688       bool
00689       _M_less(const shared_ptr<_Tp1>& __rhs) const
00690       { return _M_refcount < __rhs._M_refcount; }
00691 
00692     template<typename _Tp1> friend class shared_ptr;
00693     template<typename _Tp1> friend class weak_ptr;
00694 
00695     template<typename _Del, typename _Tp1>
00696       friend _Del* get_deleter(const shared_ptr<_Tp1>&);
00697 
00698     // friends injected into enclosing namespace and found by ADL:
00699     template<typename _Tp1>
00700       friend inline bool
00701       operator==(const shared_ptr& __a, const shared_ptr<_Tp1>& __b)
00702       { return __a.get() == __b.get(); }
00703 
00704     template<typename _Tp1>
00705       friend inline bool
00706       operator!=(const shared_ptr& __a, const shared_ptr<_Tp1>& __b)
00707       { return __a.get() != __b.get(); }
00708 
00709     template<typename _Tp1>
00710       friend inline bool
00711       operator<(const shared_ptr& __a, const shared_ptr<_Tp1>& __b)
00712       { return __a._M_less(__b); }
00713 
00714     _Tp*         _M_ptr;         // contained pointer
00715     shared_count _M_refcount;    // reference counter
00716   };  // shared_ptr
00717 
00718 // 2.2.3.8 shared_ptr specialized algorithms.
00719 template<typename _Tp>
00720   inline void
00721   swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b)
00722   { __a.swap(__b); }
00723 
00724 // 2.2.3.9 shared_ptr casts
00730 template<typename _Tp, typename _Tp1>
00731   shared_ptr<_Tp>
00732   static_pointer_cast(const shared_ptr<_Tp1>& __r)
00733   {
00734     return shared_ptr<_Tp>(__r, __static_cast_tag());
00735   }
00736 
00742 template<typename _Tp, typename _Tp1>
00743   shared_ptr<_Tp>
00744   const_pointer_cast(const shared_ptr<_Tp1>& __r)
00745   {
00746     return shared_ptr<_Tp>(__r, __const_cast_tag());
00747   }
00748 
00754 template<typename _Tp, typename _Tp1>
00755   shared_ptr<_Tp>
00756   dynamic_pointer_cast(const shared_ptr<_Tp1>& __r)
00757   {
00758     return shared_ptr<_Tp>(__r, __dynamic_cast_tag());
00759   }
00760 
00761 // 2.2.3.7 shared_ptr I/O
00762 template<typename _Ch, typename _Tr, typename _Tp>
00763   std::basic_ostream<_Ch, _Tr>&
00764   operator<<(std::basic_ostream<_Ch, _Tr>& __os, const shared_ptr<_Tp>& __p)
00765   {
00766     __os << __p.get();
00767     return __os;
00768   }
00769 
00770 // 2.2.3.10 shared_ptr get_deleter (experimental)
00771 template<typename _Del, typename _Tp>
00772   inline _Del*
00773   get_deleter(const shared_ptr<_Tp>& __p)
00774   { return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del))); }
00775 
00776 
00777 template<typename _Tp>
00778   class weak_ptr
00779   {
00780   public:
00781 
00782     typedef _Tp element_type;
00783 
00784     weak_ptr()
00785     : _M_ptr(0), _M_refcount() // never throws
00786     { }
00787 
00788     //  generated copy constructor, assignment, destructor are fine
00789 
00790     //
00791     //  The "obvious" converting constructor implementation:
00792     //
00793     //  template<class Y>
00794     //    weak_ptr(weak_ptr<Y> const & r)
00795     //    : _M_ptr(r._M_ptr), _M_refcount(r._M_refcount) // never throws
00796     //    { }
00797     //
00798     //  has a serious problem.
00799     //
00800     //  r._M_ptr may already have been invalidated. The _M_ptr(r._M_ptr)
00801     //  conversion may require access to *r._M_ptr (virtual inheritance).
00802     //
00803     //  It is not possible to avoid spurious access violations since
00804     //  in multithreaded programs r._M_ptr may be invalidated at any point.
00805     //
00806 
00807     template<typename _Tp1>
00808       weak_ptr(const weak_ptr<_Tp1>& r)
00809       : _M_refcount(r._M_refcount) // never throws
00810       {
00811         __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
00812         _M_ptr = r.lock().get();
00813       }
00814 
00815     template<typename _Tp1>
00816       weak_ptr(const shared_ptr<_Tp1>& r)
00817       : _M_ptr(r._M_ptr), _M_refcount(r._M_refcount) // never throws
00818       {
00819         __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
00820       }
00821 
00822     template<typename _Tp1>
00823       weak_ptr&
00824       operator=(const weak_ptr<_Tp1>& r) // never throws
00825       {
00826         _M_ptr = r.lock().get();
00827         _M_refcount = r._M_refcount;
00828         return *this;
00829       }
00830 
00831     template<typename _Tp1>
00832       weak_ptr&
00833       operator=(const shared_ptr<_Tp1>& r) // never throws
00834       {
00835         _M_ptr = r._M_ptr;
00836         _M_refcount = r._M_refcount;
00837         return *this;
00838       }
00839 
00840     shared_ptr<_Tp>
00841     lock() const // never throws
00842     {
00843 #ifdef __GTHREADS
00844 
00845       // optimization: avoid throw overhead
00846       if (expired())
00847     return shared_ptr<element_type>();
00848       
00849       try
00850     {
00851       return shared_ptr<element_type>(*this);
00852     }
00853       catch (const bad_weak_ptr&)
00854     {
00855       // Q: how can we get here?
00856       // A: another thread may have invalidated r after the
00857       //    use_count test above.
00858       return shared_ptr<element_type>();
00859     }
00860 
00861 #else
00862 
00863       // optimization: avoid try/catch overhead when single threaded
00864       return expired() ? shared_ptr<element_type>()
00865                    : shared_ptr<element_type>(*this);
00866 
00867 #endif
00868     } // XXX MT
00869 
00870     long
00871     use_count() const // never throws
00872     { return _M_refcount.use_count(); }
00873 
00874     bool
00875     expired() const // never throws
00876     { return _M_refcount.use_count() == 0; }
00877 
00878     void
00879     reset() // never throws
00880     { weak_ptr().swap(*this); }
00881 
00882     void
00883     swap(weak_ptr& __s) // never throws
00884     {
00885       std::swap(_M_ptr, __s._M_ptr);
00886       _M_refcount.swap(__s._M_refcount);
00887     }
00888 
00889   private:
00890 
00891     template<typename _Tp1>
00892       bool
00893       _M_less(const weak_ptr<_Tp1>& __rhs) const
00894       { return _M_refcount < __rhs._M_refcount; }
00895 
00896     // used by __enable_shared_from_this
00897     void
00898     _M_assign(_Tp* __ptr, const shared_count& __refcount)
00899     {
00900       _M_ptr = __ptr;
00901       _M_refcount = __refcount;
00902     }
00903 
00904     // friend injected into namespace and found by ADL
00905 
00906     template<typename _Tp1>
00907       friend inline bool
00908       operator<(const weak_ptr& __lhs, const weak_ptr<_Tp1>& __rhs)
00909       { return __lhs._M_less(__rhs); }
00910 
00911     template<typename _Tp1> friend class weak_ptr;
00912     template<typename _Tp1> friend class shared_ptr;
00913     friend class enable_shared_from_this<_Tp>;
00914 
00915     _Tp*       _M_ptr;           // contained pointer
00916     weak_count _M_refcount;      // reference counter
00917 
00918   };  // weak_ptr
00919 
00920 // 2.2.4.7 weak_ptr specialized algorithms.
00921 template<typename _Tp>
00922   void
00923   swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b)
00924   { __a.swap(__b); }
00925 
00926 
00927 template<typename _Tp>
00928   class enable_shared_from_this
00929   {
00930   protected:
00931 
00932     enable_shared_from_this()
00933     { }
00934 
00935     enable_shared_from_this(const enable_shared_from_this&)
00936     { }
00937 
00938     enable_shared_from_this&
00939     operator=(const enable_shared_from_this&)
00940     { return *this; }
00941 
00942     ~enable_shared_from_this()
00943     { }
00944 
00945   public:
00946 
00947     shared_ptr<_Tp>
00948     shared_from_this()
00949     {
00950       shared_ptr<_Tp> __p(this->_M_weak_this);
00951       return __p;
00952     }
00953 
00954     shared_ptr<const _Tp>
00955     shared_from_this() const
00956     {
00957       shared_ptr<const _Tp> __p(this->_M_weak_this);
00958       return __p;
00959     }
00960 
00961   private:
00962     template<typename _Tp1>
00963       void
00964       _M_weak_assign(_Tp1* __p, const shared_count& __n) const
00965       { _M_weak_this._M_assign(__p, __n); }
00966 
00967     template<typename _Tp1>
00968       friend void
00969       __enable_shared_from_this(const shared_count& __pn,
00970                 const enable_shared_from_this* __pe,
00971                 const _Tp1* __px)
00972       {
00973         if(__pe != 0)
00974           __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
00975       }
00976 
00977     mutable weak_ptr<_Tp> _M_weak_this;
00978   };
00979 
00980 } // namespace tr1
00981 } // namespace std
00982 
00983 #endif

Generated on Tue Feb 2 16:55:49 2010 for GNU C++ STL by  doxygen 1.4.7