weak_ptr.hpp

Go to the documentation of this file.
00001 #ifndef BOOST_WEAK_PTR_HPP_INCLUDED
00002 #define BOOST_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 <sysc/packages/boost/shared_ptr.hpp>
00017 
00018 #ifdef BOOST_MSVC  // moved here to work around VC++ compiler crash
00019 # pragma warning(push)
00020 # pragma warning(disable:4284) // odd return type for operator->
00021 #endif
00022 
00023 namespace boost
00024 {
00025 
00026 template<class T> class weak_ptr
00027 {
00028 private:
00029 
00030     // Borland 5.5.1 specific workarounds
00031     typedef weak_ptr<T> this_type;
00032 
00033 public:
00034 
00035     typedef T element_type;
00036 
00037     weak_ptr(): px(0), pn() // never throws in 1.30+
00038     {
00039     }
00040 
00041 //  generated copy constructor, assignment, destructor are fine
00042 
00043 
00044 //
00045 //  The "obvious" converting constructor implementation:
00046 //
00047 //  template<class Y>
00048 //  weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
00049 //  {
00050 //  }
00051 //
00052 //  has a serious problem.
00053 //
00054 //  r.px may already have been invalidated. The px(r.px)
00055 //  conversion may require access to *r.px (virtual inheritance).
00056 //
00057 //  It is not possible to avoid spurious access violations since
00058 //  in multithreaded programs r.px may be invalidated at any point.
00059 //
00060 
00061     template<class Y>
00062     weak_ptr(weak_ptr<Y> const & r): pn(r.pn) // never throws
00063     {
00064         px = r.lock().get();
00065     }
00066 
00067     template<class Y>
00068     weak_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
00069     {
00070     }
00071 
00072 #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
00073 
00074     template<class Y>
00075     weak_ptr & operator=(weak_ptr<Y> const & r) // never throws
00076     {
00077         px = r.lock().get();
00078         pn = r.pn;
00079         return *this;
00080     }
00081 
00082     template<class Y>
00083     weak_ptr & operator=(shared_ptr<Y> const & r) // never throws
00084     {
00085         px = r.px;
00086         pn = r.pn;
00087         return *this;
00088     }
00089 
00090 #endif
00091 
00092     shared_ptr<T> lock() const // never throws
00093     {
00094 #if defined(BOOST_HAS_THREADS)
00095 
00096         // optimization: avoid throw overhead
00097         if(expired())
00098         {
00099             return shared_ptr<element_type>();
00100         }
00101 
00102         try
00103         {
00104             return shared_ptr<element_type>(*this);
00105         }
00106         catch(bad_weak_ptr const &)
00107         {
00108             // Q: how can we get here?
00109             // A: another thread may have invalidated r after the use_count test above.
00110             return shared_ptr<element_type>();
00111         }
00112 
00113 #else
00114 
00115         // optimization: avoid try/catch overhead when single threaded
00116         return expired()? shared_ptr<element_type>(): shared_ptr<element_type>(*this);
00117 
00118 #endif
00119     }
00120 
00121     long use_count() const // never throws
00122     {
00123         return pn.use_count();
00124     }
00125 
00126     bool expired() const // never throws
00127     {
00128         return pn.use_count() == 0;
00129     }
00130 
00131     void reset() // never throws in 1.30+
00132     {
00133         this_type().swap(*this);
00134     }
00135 
00136     void swap(this_type & other) // never throws
00137     {
00138         std::swap(px, other.px);
00139         pn.swap(other.pn);
00140     }
00141 
00142     void _internal_assign(T * px2, detail::shared_count const & pn2)
00143     {
00144         px = px2;
00145         pn = pn2;
00146     }
00147 
00148     template<class Y> bool _internal_less(weak_ptr<Y> const & rhs) const
00149     {
00150         return pn < rhs.pn;
00151     }
00152 
00153 // Tasteless as this may seem, making all members public allows member templates
00154 // to work in the absence of member template friends. (Matthew Langston)
00155 
00156 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
00157 
00158 private:
00159 
00160     template<class Y> friend class weak_ptr;
00161     template<class Y> friend class shared_ptr;
00162 
00163 #endif
00164 
00165     T * px;                     // contained pointer
00166     detail::weak_count pn;      // reference counter
00167 
00168 };  // weak_ptr
00169 
00170 template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b)
00171 {
00172     return a._internal_less(b);
00173 }
00174 
00175 template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
00176 {
00177     a.swap(b);
00178 }
00179 
00180 // deprecated, provided for backward compatibility
00181 template<class T> shared_ptr<T> make_shared(weak_ptr<T> const & r)
00182 {
00183     return r.lock();
00184 }
00185 
00186 } // namespace boost
00187 
00188 #ifdef BOOST_MSVC
00189 # pragma warning(pop)
00190 #endif    
00191 
00192 #endif  // #ifndef BOOST_WEAK_PTR_HPP_INCLUDED

Generated on Wed Jan 21 15:32:10 2009 for SystemC by  doxygen 1.5.5