00001 #ifndef toast_weak_unintrusive_ptr_hpp_INCLUDED 00002 #define toast_weak_unintrusive_ptr_hpp_INCLUDED 00003 00004 #include <toast/unintrusive_ptr.hpp> 00005 #include <toast/detail/unintrusive_impl.hpp> 00006 00007 #include <algorithm> 00008 00009 #include <boost/static_assert.hpp> 00010 #include <boost/type_traits/is_convertible.hpp> 00011 00019 namespace toast { 00020 00021 template<class T> 00022 class unintrusive_ptr; 00023 00041 template<class T> 00042 class weak_unintrusive_ptr 00043 { 00044 typedef detail::count_wrapper<T> real_count_wrapper_t; 00045 typedef detail::weak_count_wrapper<T> real_wrapper_t; 00046 00047 public: 00048 typedef T element_type; 00049 00050 weak_unintrusive_ptr() 00051 { 00052 set_new_wrapper(detail::the_weak_zero_wrapper()); 00053 } 00054 00055 weak_unintrusive_ptr(weak_unintrusive_ptr const & r) 00056 { 00057 set_new_wrapper(r.m_wrapper); 00058 } 00059 00060 template<class Y> 00061 explicit weak_unintrusive_ptr(weak_unintrusive_ptr<Y> const & r) 00062 { 00063 BOOST_STATIC_ASSERT((boost::is_convertible<Y*, T*>::value)); 00064 00065 set_new_wrapper(r.m_wrapper); 00066 } 00067 00073 template<class Y> 00074 weak_unintrusive_ptr(unintrusive_ptr<Y> const & r) 00075 { 00076 BOOST_STATIC_ASSERT((boost::is_convertible<Y*, T*>::value)); 00077 00078 real_count_wrapper_t* unintrusive_wrapper = static_cast<real_count_wrapper_t*>(r.m_wrapper); 00079 00080 if(unintrusive_wrapper->m_weak_wrapper == detail::the_weak_zero_wrapper()) 00081 unintrusive_wrapper->m_weak_wrapper = new detail::weak_count_wrapper<Y>(unintrusive_wrapper); 00082 00083 set_new_wrapper(unintrusive_wrapper->m_weak_wrapper); 00084 } 00085 00086 ~weak_unintrusive_ptr() 00087 { 00088 decrement(); 00089 }; 00090 00091 weak_unintrusive_ptr& operator=(weak_unintrusive_ptr const & r) 00092 { 00093 decrement(); 00094 set_new_wrapper(r.m_wrapper); 00095 00096 return *this; 00097 } 00098 00099 template<class Y> 00100 weak_unintrusive_ptr& operator=(weak_unintrusive_ptr<Y> const & r) 00101 { 00102 (void)static_cast<T*>((Y*)NULL); 00103 00104 decrement(); 00105 set_new_wrapper(r.m_wrapper); 00106 } 00107 00108 template<class Y> 00109 weak_unintrusive_ptr& operator=(unintrusive_ptr<Y> const & r) 00110 { 00111 real_count_wrapper_t* unintrusive_wrapper = static_cast<real_count_wrapper_t*>(r.m_wrapper); 00112 00113 (void)static_cast<T*>((Y*)NULL); 00114 00115 decrement(); 00116 00117 if(unintrusive_wrapper->m_weak_wrapper == detail::the_weak_zero_wrapper()) 00118 unintrusive_wrapper->m_weak_wrapper = new detail::weak_count_wrapper<Y>(unintrusive_wrapper); 00119 00120 detail::weak_count_wrapper_base* new_wrapper = static_cast<real_count_wrapper_t*>(r.m_wrapper)->m_weak_wrapper; 00121 set_new_wrapper(new_wrapper); 00122 00123 return *this; 00124 } 00125 00126 long use_count() const 00127 { 00128 return m_wrapper->count(); 00129 } 00130 00131 bool expired() const 00132 { 00133 return static_cast<real_wrapper_t*>(m_wrapper)->expired(); 00134 } 00135 00136 unintrusive_ptr<T> lock() const 00137 { 00138 if(expired()) 00139 return unintrusive_ptr<T>(); 00140 00141 return unintrusive_ptr<T>(static_cast<detail::count_wrapper_base*> 00142 (static_cast<real_wrapper_t*>(m_wrapper) 00143 ->m_real_wrapper)); 00144 } 00145 00146 void reset() 00147 { 00148 decrement(); 00149 set_new_wrapper(detail::the_weak_zero_wrapper()); 00150 } 00151 00152 void swap(weak_unintrusive_ptr<T> & b) 00153 { 00154 std::swap(m_wrapper, b.m_wrapper); 00155 } 00156 00157 private: 00158 void decrement() 00159 { 00160 if(m_wrapper->decrement() == 0) { 00161 delete m_wrapper; 00162 set_new_wrapper(detail::the_weak_zero_wrapper()); 00163 return; 00164 } 00165 } 00166 00167 void set_new_wrapper(detail::weak_count_wrapper_base* new_wrapper) 00168 { 00169 new_wrapper->increment(); 00170 m_wrapper = new_wrapper; 00171 } 00172 00173 template<int n> 00174 friend class count_wrapper; 00175 00176 template<class Y> 00177 friend class unintrusive_ptr; 00178 00179 detail::weak_count_wrapper_base* m_wrapper; 00180 }; 00181 00182 template<class T, class U> 00183 bool operator<(weak_unintrusive_ptr<T> const & a, weak_unintrusive_ptr<U> const & b) 00184 { 00185 return a.m_wrapper < b.m_wrapper; 00186 } 00187 00188 template<class T> 00189 void swap(weak_unintrusive_ptr<T> & a, weak_unintrusive_ptr<T> & b) 00190 { 00191 a.swap(b); 00192 } 00193 00196 } 00197 00198 #endif