CppCMS
booster/weak_ptr.h
00001 #ifndef BOOSTER_SMART_PTR_WEAK_PTR_HPP_INCLUDED
00002 #define BOOSTER_SMART_PTR_WEAK_PTR_HPP_INCLUDED
00003 
00004 //
00005 //  weak_ptr.hpp
00006 //
00007 //  Copyright (c) 2001, 2002, 2003 Peter Dimov
00008 //
00009 // Distributed under the Boost Software License, Version 1.0. (See
00010 // accompanying file LICENSE_1_0.txt or copy at
00011 // http://www.boost.org/LICENSE_1_0.txt)
00012 //
00013 //  See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation.
00014 //
00015 
00016 #include <memory> // boost.TR1 include order fix
00017 #include <booster/smart_ptr/shared_count.h>
00018 #include <booster/shared_ptr.h>
00019 
00020 #ifdef BOOSTER_MSVC  // moved here to work around VC++ compiler crash
00021 # pragma warning(push)
00022 # pragma warning(disable:4284) // odd return type for operator->
00023 #endif
00024 
00025 namespace booster
00026 {
00027 
00028 template<class T> class weak_ptr
00029 {
00030 private:
00031 
00032     // Borland 5.5.1 specific workarounds
00033     typedef weak_ptr<T> this_type;
00034 
00035 public:
00036 
00037     typedef T element_type;
00038 
00039     weak_ptr(): px(0), pn() // never throws in 1.30+
00040     {
00041     }
00042 
00043 //  generated copy constructor, assignment, destructor are fine
00044 
00045 
00046 //
00047 //  The "obvious" converting constructor implementation:
00048 //
00049 //  template<class Y>
00050 //  weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
00051 //  {
00052 //  }
00053 //
00054 //  has a serious problem.
00055 //
00056 //  r.px may already have been invalidated. The px(r.px)
00057 //  conversion may require access to *r.px (virtual inheritance).
00058 //
00059 //  It is not possible to avoid spurious access violations since
00060 //  in multithreaded programs r.px may be invalidated at any point.
00061 //
00062 
00063     template<class Y>
00064     weak_ptr( weak_ptr<Y> const & r, typename detail::sp_enable_if_convertible<Y,T>::type = detail::sp_empty() )
00065     : px(r.lock().get()), pn(r.pn) // never throws
00066     {
00067     }
00068 
00069 
00070     template<class Y>
00071     weak_ptr( shared_ptr<Y> const & r, typename detail::sp_enable_if_convertible<Y,T>::type = detail::sp_empty() )
00072     : px( r.px ), pn( r.pn ) // never throws
00073     {
00074     }
00075 
00076     template<class Y>
00077     weak_ptr & operator=(weak_ptr<Y> const & r) // never throws
00078     {
00079         px = r.lock().get();
00080         pn = r.pn;
00081         return *this;
00082     }
00083 
00084     template<class Y>
00085     weak_ptr & operator=(shared_ptr<Y> const & r) // never throws
00086     {
00087         px = r.px;
00088         pn = r.pn;
00089         return *this;
00090     }
00091 
00092     shared_ptr<T> lock() const // never throws
00093     {
00094         return shared_ptr<element_type>( *this, booster::detail::sp_nothrow_tag() );
00095     }
00096 
00097     long use_count() const // never throws
00098     {
00099         return pn.use_count();
00100     }
00101 
00102     bool expired() const // never throws
00103     {
00104         return pn.use_count() == 0;
00105     }
00106 
00107     bool _empty() const // extension, not in std::weak_ptr
00108     {
00109         return pn.empty();
00110     }
00111 
00112     void reset() // never throws in 1.30+
00113     {
00114         this_type().swap(*this);
00115     }
00116 
00117     void swap(this_type & other) // never throws
00118     {
00119         std::swap(px, other.px);
00120         pn.swap(other.pn);
00121     }
00122 
00123     void _internal_assign(T * px2, booster::detail::shared_count const & pn2)
00124     {
00125         px = px2;
00126         pn = pn2;
00127     }
00128 
00129     template<class Y> bool _internal_less(weak_ptr<Y> const & rhs) const
00130     {
00131         return pn < rhs.pn;
00132     }
00133 
00134 // Tasteless as this may seem, making all members public allows member templates
00135 // to work in the absence of member template friends. (Matthew Langston)
00136 
00137 private:
00138 
00139     template<class Y> friend class weak_ptr;
00140     template<class Y> friend class shared_ptr;
00141 
00142     T * px;                       // contained pointer
00143     booster::detail::weak_count pn; // reference counter
00144 
00145 };  // weak_ptr
00146 
00147 template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b)
00148 {
00149     return a._internal_less(b);
00150 }
00151 
00152 template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
00153 {
00154     a.swap(b);
00155 }
00156 
00157 } // namespace boost
00158 
00159 #ifdef BOOSTER_MSVC
00160 # pragma warning(pop)
00161 #endif    
00162 
00163 #endif  // #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED