shared_ptr.h

Go to the documentation of this file.
00001 // shared_ptr and weak_ptr implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2007, 2008, 2009 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 3, 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 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 // GCC Note: Based on files from version 1.32.0 of the Boost library.
00026 
00027 //  shared_count.hpp
00028 //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
00029 
00030 //  shared_ptr.hpp
00031 //  Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
00032 //  Copyright (C) 2001, 2002, 2003 Peter Dimov
00033 
00034 //  weak_ptr.hpp
00035 //  Copyright (C) 2001, 2002, 2003 Peter Dimov
00036 
00037 //  enable_shared_from_this.hpp
00038 //  Copyright (C) 2002 Peter Dimov
00039 
00040 // Distributed under the Boost Software License, Version 1.0. (See
00041 // accompanying file LICENSE_1_0.txt or copy at
00042 // http://www.boost.org/LICENSE_1_0.txt)
00043 
00044 /** @file bits/shared_ptr.h
00045  *  This is an internal header file, included by other library headers.
00046  *  You should not attempt to use it directly.
00047  */
00048 
00049 #ifndef _SHARED_PTR_H
00050 #define _SHARED_PTR_H 1
00051 
00052 #ifndef __GXX_EXPERIMENTAL_CXX0X__
00053 # include <c++0x_warning.h>
00054 #endif
00055 
00056 #include <bits/shared_ptr_base.h>
00057 
00058 _GLIBCXX_BEGIN_NAMESPACE(std)
00059 
00060   /**
00061    * @addtogroup pointer_abstractions
00062    * @{
00063    */
00064 
00065   /// 2.2.3.7 shared_ptr I/O
00066   template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
00067     std::basic_ostream<_Ch, _Tr>&
00068     operator<<(std::basic_ostream<_Ch, _Tr>& __os,
00069            const __shared_ptr<_Tp, _Lp>& __p)
00070     {
00071       __os << __p.get();
00072       return __os;
00073     }
00074 
00075   /// 2.2.3.10 shared_ptr get_deleter (experimental)
00076   template<typename _Del, typename _Tp, _Lock_policy _Lp>
00077     inline _Del*
00078     get_deleter(const __shared_ptr<_Tp, _Lp>& __p)
00079     {
00080 #ifdef __GXX_RTTI
00081       return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
00082 #else
00083       return 0;
00084 #endif
00085     }
00086 
00087 
00088   /**
00089    *  @brief  A smart pointer with reference-counted copy semantics.
00090    *
00091    *  The object pointed to is deleted when the last shared_ptr pointing to
00092    *  it is destroyed or reset.
00093   */
00094   template<typename _Tp>
00095     class shared_ptr : public __shared_ptr<_Tp>
00096     {
00097     public:
00098       /**
00099        *  @brief  Construct an empty %shared_ptr.
00100        *  @post   use_count()==0 && get()==0
00101        */
00102       shared_ptr() : __shared_ptr<_Tp>() { }
00103 
00104       /**
00105        *  @brief  Construct a %shared_ptr that owns the pointer @a __p.
00106        *  @param  __p  A pointer that is convertible to element_type*.
00107        *  @post   use_count() == 1 && get() == __p
00108        *  @throw  std::bad_alloc, in which case @c delete @a __p is called.
00109        */
00110       template<typename _Tp1>
00111     explicit shared_ptr(_Tp1* __p) : __shared_ptr<_Tp>(__p) { }
00112 
00113       /**
00114        *  @brief  Construct a %shared_ptr that owns the pointer @a __p
00115        *          and the deleter @a __d.
00116        *  @param  __p  A pointer.
00117        *  @param  __d  A deleter.
00118        *  @post   use_count() == 1 && get() == __p
00119        *  @throw  std::bad_alloc, in which case @a __d(__p) is called.
00120        *
00121        *  Requirements: _Deleter's copy constructor and destructor must
00122        *  not throw
00123        *
00124        *  __shared_ptr will release __p by calling __d(__p)
00125        */
00126     template<typename _Tp1, typename _Deleter>
00127     shared_ptr(_Tp1* __p, _Deleter __d) : __shared_ptr<_Tp>(__p, __d) { }
00128 
00129       /**
00130        *  @brief  Construct a %shared_ptr that owns the pointer @a __p
00131        *          and the deleter @a __d.
00132        *  @param  __p  A pointer.
00133        *  @param  __d  A deleter.
00134        *  @param  __a  An allocator.
00135        *  @post   use_count() == 1 && get() == __p
00136        *  @throw  std::bad_alloc, in which case @a __d(__p) is called.
00137        *
00138        *  Requirements: _Deleter's copy constructor and destructor must
00139        *  not throw _Alloc's copy constructor and destructor must not
00140        *  throw.
00141        *
00142        *  __shared_ptr will release __p by calling __d(__p)
00143        */
00144       template<typename _Tp1, typename _Deleter, typename _Alloc>
00145     shared_ptr(_Tp1* __p, _Deleter __d, const _Alloc& __a)
00146     : __shared_ptr<_Tp>(__p, __d, __a) { }
00147 
00148       // Aliasing constructor
00149 
00150       /**
00151        *  @brief  Constructs a %shared_ptr instance that stores @a __p
00152        *          and shares ownership with @a __r.
00153        *  @param  __r  A %shared_ptr.
00154        *  @param  __p  A pointer that will remain valid while @a *__r is valid.
00155        *  @post   get() == __p && use_count() == __r.use_count()
00156        *
00157        *  This can be used to construct a @c shared_ptr to a sub-object
00158        *  of an object managed by an existing @c shared_ptr.
00159        *
00160        * @code
00161        * shared_ptr< pair<int,int> > pii(new pair<int,int>());
00162        * shared_ptr<int> pi(pii, &pii->first);
00163        * assert(pii.use_count() == 2);
00164        * @endcode
00165        */
00166       template<typename _Tp1>
00167     shared_ptr(const shared_ptr<_Tp1>& __r, _Tp* __p)
00168     : __shared_ptr<_Tp>(__r, __p) { }
00169 
00170       /**
00171        *  @brief  If @a __r is empty, constructs an empty %shared_ptr;
00172        *          otherwise construct a %shared_ptr that shares ownership
00173        *          with @a __r.
00174        *  @param  __r  A %shared_ptr.
00175        *  @post   get() == __r.get() && use_count() == __r.use_count()
00176        */
00177       template<typename _Tp1>
00178     shared_ptr(const shared_ptr<_Tp1>& __r) : __shared_ptr<_Tp>(__r) { }
00179 
00180       /**
00181        *  @brief  Move-constructs a %shared_ptr instance from @a __r.
00182        *  @param  __r  A %shared_ptr rvalue.
00183        *  @post   *this contains the old value of @a __r, @a __r is empty.
00184        */
00185       shared_ptr(shared_ptr&& __r)
00186       : __shared_ptr<_Tp>(std::move(__r)) { }
00187 
00188       /**
00189        *  @brief  Move-constructs a %shared_ptr instance from @a __r.
00190        *  @param  __r  A %shared_ptr rvalue.
00191        *  @post   *this contains the old value of @a __r, @a __r is empty.
00192        */
00193       template<typename _Tp1>
00194     shared_ptr(shared_ptr<_Tp1>&& __r)
00195     : __shared_ptr<_Tp>(std::move(__r)) { }
00196 
00197       /**
00198        *  @brief  Constructs a %shared_ptr that shares ownership with @a __r
00199        *          and stores a copy of the pointer stored in @a __r.
00200        *  @param  __r  A weak_ptr.
00201        *  @post   use_count() == __r.use_count()
00202        *  @throw  bad_weak_ptr when __r.expired(),
00203        *          in which case the constructor has no effect.
00204        */
00205       template<typename _Tp1>
00206     explicit shared_ptr(const weak_ptr<_Tp1>& __r)
00207     : __shared_ptr<_Tp>(__r) { }
00208 
00209 #if _GLIBCXX_DEPRECATED
00210       template<typename _Tp1>
00211     explicit
00212     shared_ptr(std::auto_ptr<_Tp1>&& __r)
00213     : __shared_ptr<_Tp>(std::move(__r)) { }
00214 #endif
00215 
00216       template<typename _Tp1, typename _Del>
00217     explicit shared_ptr(const std::unique_ptr<_Tp1, _Del>&) = delete;
00218 
00219       template<typename _Tp1, typename _Del>
00220     explicit shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
00221     : __shared_ptr<_Tp>(std::move(__r)) { }
00222 
00223       template<typename _Tp1>
00224     shared_ptr&
00225     operator=(const shared_ptr<_Tp1>& __r) // never throws
00226     {
00227       this->__shared_ptr<_Tp>::operator=(__r);
00228       return *this;
00229     }
00230 
00231 #if _GLIBCXX_DEPRECATED
00232       template<typename _Tp1>
00233     shared_ptr&
00234     operator=(std::auto_ptr<_Tp1>&& __r)
00235     {
00236       this->__shared_ptr<_Tp>::operator=(std::move(__r));
00237       return *this;
00238     }
00239 #endif
00240 
00241       shared_ptr&
00242       operator=(shared_ptr&& __r)
00243       {
00244     this->__shared_ptr<_Tp>::operator=(std::move(__r));
00245     return *this;
00246       }
00247 
00248       template<class _Tp1>
00249     shared_ptr&
00250     operator=(shared_ptr<_Tp1>&& __r)
00251     {
00252       this->__shared_ptr<_Tp>::operator=(std::move(__r));
00253       return *this;
00254     }
00255 
00256       template<typename _Tp1, typename _Del>
00257     shared_ptr&
00258     operator=(const std::unique_ptr<_Tp1, _Del>& __r) = delete;
00259 
00260       template<typename _Tp1, typename _Del>
00261     shared_ptr&
00262     operator=(std::unique_ptr<_Tp1, _Del>&& __r)
00263     {
00264       this->__shared_ptr<_Tp>::operator=(std::move(__r));
00265       return *this;
00266     }
00267 
00268     private:
00269       // This constructor is non-standard, it is used by allocate_shared.
00270       template<typename _Alloc, typename... _Args>
00271     shared_ptr(_Sp_make_shared_tag __tag, _Alloc __a, _Args&&... __args)
00272     : __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...)
00273     { }
00274 
00275       template<typename _Tp1, typename _Alloc, typename... _Args>
00276     friend shared_ptr<_Tp1>
00277     allocate_shared(_Alloc __a, _Args&&... __args);
00278     };
00279 
00280   // 20.8.13.2.7 shared_ptr comparisons
00281   template<typename _Tp1, typename _Tp2>
00282     inline bool
00283     operator==(const shared_ptr<_Tp1>& __a, const shared_ptr<_Tp2>& __b)
00284     { return __a.get() == __b.get(); }
00285 
00286   template<typename _Tp1, typename _Tp2>
00287     inline bool
00288     operator!=(const shared_ptr<_Tp1>& __a, const shared_ptr<_Tp2>& __b)
00289     { return __a.get() != __b.get(); }
00290 
00291   template<typename _Tp1, typename _Tp2>
00292     inline bool
00293     operator<(const shared_ptr<_Tp1>& __a, const shared_ptr<_Tp2>& __b)
00294     { return __a.get() < __b.get(); }
00295 
00296   template<typename _Tp>
00297     struct less<shared_ptr<_Tp>> : public _Sp_less<shared_ptr<_Tp>>
00298     { };
00299 
00300   // 20.8.13.2.9 shared_ptr specialized algorithms.
00301   template<typename _Tp>
00302     inline void
00303     swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b)
00304     { __a.swap(__b); }
00305 
00306   // 20.8.13.2.10 shared_ptr casts.
00307   template<typename _Tp, typename _Tp1>
00308     inline shared_ptr<_Tp>
00309     static_pointer_cast(const shared_ptr<_Tp1>& __r)
00310     { return shared_ptr<_Tp>(__r, static_cast<_Tp*>(__r.get())); }
00311 
00312   template<typename _Tp, typename _Tp1>
00313     inline shared_ptr<_Tp>
00314     const_pointer_cast(const shared_ptr<_Tp1>& __r)
00315     { return shared_ptr<_Tp>(__r, const_cast<_Tp*>(__r.get())); }
00316 
00317   template<typename _Tp, typename _Tp1>
00318     inline shared_ptr<_Tp>
00319     dynamic_pointer_cast(const shared_ptr<_Tp1>& __r)
00320     {
00321       if (_Tp* __p = dynamic_cast<_Tp*>(__r.get()))
00322     return shared_ptr<_Tp>(__r, __p);
00323       return shared_ptr<_Tp>();
00324     }
00325 
00326 
00327   /**
00328    *  @brief  A smart pointer with weak semantics.
00329    *
00330    *  With forwarding constructors and assignment operators.
00331    */
00332   template<typename _Tp>
00333     class weak_ptr : public __weak_ptr<_Tp>
00334     {
00335     public:
00336       weak_ptr() : __weak_ptr<_Tp>() { }
00337 
00338       template<typename _Tp1>
00339     weak_ptr(const weak_ptr<_Tp1>& __r)
00340     : __weak_ptr<_Tp>(__r) { }
00341 
00342       template<typename _Tp1>
00343     weak_ptr(const shared_ptr<_Tp1>& __r)
00344     : __weak_ptr<_Tp>(__r) { }
00345 
00346       template<typename _Tp1>
00347     weak_ptr&
00348     operator=(const weak_ptr<_Tp1>& __r) // never throws
00349     {
00350       this->__weak_ptr<_Tp>::operator=(__r);
00351       return *this;
00352     }
00353 
00354       template<typename _Tp1>
00355     weak_ptr&
00356     operator=(const shared_ptr<_Tp1>& __r) // never throws
00357     {
00358       this->__weak_ptr<_Tp>::operator=(__r);
00359       return *this;
00360     }
00361 
00362       shared_ptr<_Tp>
00363       lock() const // never throws
00364       {
00365 #ifdef __GTHREADS
00366     if (this->expired())
00367       return shared_ptr<_Tp>();
00368 
00369     __try
00370       {
00371         return shared_ptr<_Tp>(*this);
00372       }
00373     __catch(const bad_weak_ptr&)
00374       {
00375         return shared_ptr<_Tp>();
00376       }
00377 #else
00378     return this->expired() ? shared_ptr<_Tp>() : shared_ptr<_Tp>(*this);
00379 #endif
00380       }
00381 
00382       // Comparisons
00383       template<typename _Tp1>
00384     bool operator<(const weak_ptr<_Tp1>&) const = delete;
00385       template<typename _Tp1>
00386     bool operator<=(const weak_ptr<_Tp1>&) const = delete;
00387       template<typename _Tp1>
00388     bool operator>(const weak_ptr<_Tp1>&) const = delete;
00389       template<typename _Tp1>
00390     bool operator>=(const weak_ptr<_Tp1>&) const = delete;
00391     };
00392 
00393   // 20.8.13.3.7 weak_ptr specialized algorithms.
00394   template<typename _Tp>
00395     inline void
00396     swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b)
00397     { __a.swap(__b); }
00398 
00399 
00400   /// Primary template owner_less
00401   template<typename _Tp>
00402     struct owner_less;
00403 
00404   /// Partial specialization of owner_less for shared_ptr.
00405   template<typename _Tp>
00406     struct owner_less<shared_ptr<_Tp>>
00407     : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>>
00408     { };
00409 
00410   /// Partial specialization of owner_less for weak_ptr.
00411   template<typename _Tp>
00412     struct owner_less<weak_ptr<_Tp>>
00413     : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
00414     { };
00415 
00416   /**
00417    *  @brief Base class allowing use of member function shared_from_this.
00418    */
00419   template<typename _Tp>
00420     class enable_shared_from_this
00421     {
00422     protected:
00423       enable_shared_from_this() { }
00424 
00425       enable_shared_from_this(const enable_shared_from_this&) { }
00426 
00427       enable_shared_from_this&
00428       operator=(const enable_shared_from_this&)
00429       { return *this; }
00430 
00431       ~enable_shared_from_this() { }
00432 
00433     public:
00434       shared_ptr<_Tp>
00435       shared_from_this()
00436       { return shared_ptr<_Tp>(this->_M_weak_this); }
00437 
00438       shared_ptr<const _Tp>
00439       shared_from_this() const
00440       { return shared_ptr<const _Tp>(this->_M_weak_this); }
00441 
00442     private:
00443       template<typename _Tp1>
00444     void
00445     _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const
00446     { _M_weak_this._M_assign(__p, __n); }
00447 
00448       template<typename _Tp1>
00449     friend void
00450     __enable_shared_from_this_helper(const __shared_count<>& __pn,
00451                      const enable_shared_from_this* __pe,
00452                      const _Tp1* __px)
00453     {
00454       if (__pe != 0)
00455         __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
00456     }
00457 
00458       mutable weak_ptr<_Tp>  _M_weak_this;
00459     };
00460 
00461   /**
00462    *  @brief  Create an object that is owned by a shared_ptr.
00463    *  @param  __a     An allocator.
00464    *  @param  __args  Arguments for the @a _Tp object's constructor.
00465    *  @return A shared_ptr that owns the newly created object.
00466    *  @throw  An exception thrown from @a _Alloc::allocate or from the
00467    *          constructor of @a _Tp.
00468    *
00469    *  A copy of @a __a will be used to allocate memory for the shared_ptr
00470    *  and the new object.
00471    */
00472   template<typename _Tp, typename _Alloc, typename... _Args>
00473     inline shared_ptr<_Tp>
00474     allocate_shared(_Alloc __a, _Args&&... __args)
00475     {
00476       return shared_ptr<_Tp>(_Sp_make_shared_tag(), std::forward<_Alloc>(__a),
00477                  std::forward<_Args>(__args)...);
00478     }
00479 
00480   /**
00481    *  @brief  Create an object that is owned by a shared_ptr.
00482    *  @param  __args  Arguments for the @a _Tp object's constructor.
00483    *  @return A shared_ptr that owns the newly created object.
00484    *  @throw  std::bad_alloc, or an exception thrown from the
00485    *          constructor of @a _Tp.
00486    */
00487   template<typename _Tp, typename... _Args>
00488     inline shared_ptr<_Tp>
00489     make_shared(_Args&&... __args)
00490     {
00491       typedef typename std::remove_const<_Tp>::type _Tp_nc;
00492       return allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
00493                   std::forward<_Args>(__args)...);
00494     }
00495 
00496   // @} group pointer_abstractions
00497 
00498 _GLIBCXX_END_NAMESPACE
00499 
00500 #endif // _SHARED_PTR_H

Generated on 11 Jan 2010 for libstdc++ by  doxygen 1.6.1