00001 #ifndef toast_unintrusive_ptr_hpp_INCLUDED
00002 #define toast_unintrusive_ptr_hpp_INCLUDED
00003
00004 #include <iostream>
00005 #include <algorithm>
00006
00007 #include <boost/static_assert.hpp>
00008 #include <boost/utility/enable_if.hpp>
00009 #include <boost/type_traits/is_base_of.hpp>
00010 #include <boost/type_traits/is_convertible.hpp>
00011
00012 #include <toast/detail/unintrusive_impl.hpp>
00013
00021 namespace toast {
00022
00023 template<class T>
00024 class unintrusive_ptr;
00025
00026 namespace detail {
00027
00028 template<class T>
00029 int get_use_count(unintrusive_ptr<T> const &x)
00030 {
00031 return x.use_count();
00032 }
00033
00034 template<class T>
00035 bool get_unique(unintrusive_ptr<T> const &x)
00036 {
00037 return x.unique();
00038 }
00039
00040 }
00041
00042 template<class T>
00043 class weak_unintrusive_ptr;
00044
00045 template<class T>
00046 class enable_unintrusive_from_this;
00047
00094 template<class T>
00095 class unintrusive_ptr
00096 {
00097 typedef detail::weak_count_wrapper<T> real_weak_wrapper_t;
00098 typedef detail::count_wrapper<T> real_wrapper_t;
00099 public:
00100 typedef T element_type;
00101
00102 typedef T*(unintrusive_ptr<T>::*unspecified_bool_type)() const;
00103
00104 unintrusive_ptr()
00105 {
00106 set_new_wrapper(detail::the_zero_wrapper());
00107 }
00108
00109 template<class TypedInPlaceFactory>
00110 unintrusive_ptr(TypedInPlaceFactory const &factory)
00111 {
00112 build_new_wrapper(factory);
00113 }
00114
00115 unintrusive_ptr(unintrusive_ptr const &toCopy)
00116 {
00117 set_new_wrapper(toCopy.m_wrapper);
00118 }
00119
00120 template<class Y>
00121 unintrusive_ptr(unintrusive_ptr<Y> const &other)
00122 {
00123 BOOST_STATIC_ASSERT((boost::is_convertible<Y*, T*>::value) || (boost::is_convertible<T*, Y*>::value));
00124 detail::program_startup_multiple_inheritance_check<T, Y>::instantiate_template();
00125
00126 set_new_wrapper(other.m_wrapper);
00127 }
00128
00129 template<class Y>
00130 explicit unintrusive_ptr(weak_unintrusive_ptr<Y> const & r)
00131 {
00132 real_wrapper_t* r_real_wrapper = static_cast<real_weak_wrapper_t*>(r.m_wrapper)->m_real_wrapper;
00133
00134 if(r_real_wrapper == NULL)
00135 throw bad_weak_unintrusive_ptr();
00136
00137 set_new_wrapper(r_real_wrapper);
00138 }
00139
00140
00141 unintrusive_ptr& operator=(unintrusive_ptr const &target)
00142 {
00143 return operator=<T>(target);
00144 }
00145
00146 template<class Y>
00147 unintrusive_ptr<T>& operator=(unintrusive_ptr<Y> const &target)
00148 {
00149 BOOST_STATIC_ASSERT((boost::is_convertible<Y*, T*>::value) || (boost::is_convertible<T*, Y*>::value));
00150 detail::program_startup_multiple_inheritance_check<T, Y>::instantiate_template();
00151
00152 unintrusive_ptr<T>(target).swap(*this);
00153 return *this;
00154 }
00155
00156 ~unintrusive_ptr()
00157 {
00158 decrement();
00159 }
00160
00161 void reset()
00162 {
00163 decrement();
00164 set_new_wrapper(detail::the_zero_wrapper());
00165 }
00166
00167 template<class TypedInPlaceFactory>
00168 void reset(TypedInPlaceFactory const &factory)
00169 {
00170 typedef detail::count_wrapper<T> real_wrapper_t;
00171
00172 decrement();
00173 build_new_wrapper(factory);
00174 }
00175
00176 T& operator*() const
00177 {
00178 return *get();
00179 }
00180
00181 T* operator->() const
00182 {
00183 return static_cast<T*>
00184 (static_cast<real_wrapper_t*>(m_wrapper)->stored_object());
00185 }
00186
00187 T* get() const
00188 {
00189 if(!is_null())
00190 return static_cast<T*>(static_cast<real_wrapper_t*>(m_wrapper)->stored_object());
00191 else
00192 return NULL;
00193 }
00194
00195 operator unspecified_bool_type() const
00196 {
00197 return is_null() ? NULL : &unintrusive_ptr<T>::get;
00198 }
00199
00200 void swap(unintrusive_ptr<T>& other)
00201 {
00202 std::swap(m_wrapper, other.m_wrapper);
00203 }
00204
00205 private:
00210 bool unique() const
00211 {
00212 return !is_null() ? m_wrapper->count() == 1 : false;
00213 }
00214
00219 long use_count() const
00220 {
00221 return !is_null() ? m_wrapper->count() : 0;
00222 }
00223
00224
00225 explicit unintrusive_ptr(detail::count_wrapper_base* wrapper)
00226 {
00227 set_new_wrapper(wrapper);
00228 }
00229
00230 template<class TypedInPlaceFactory>
00231 void build_new_wrapper(TypedInPlaceFactory const &factory)
00232 {
00233 typedef detail::count_wrapper<typename TypedInPlaceFactory::value_type> real_wrapper_t;
00234
00235 real_wrapper_t* tmp = new real_wrapper_t;
00236 tmp->init(factory);
00237
00238 m_wrapper = tmp;
00239
00240 optionally_setup_internal_weak_this_p<TypedInPlaceFactory>(get());
00241 }
00242
00243 template<class TypedInPlaceFactory>
00244 void optionally_setup_internal_weak_this_p(typename boost::disable_if<
00245 boost::is_base_of<
00246 enable_unintrusive_from_this<typename TypedInPlaceFactory::value_type>,
00247 typename TypedInPlaceFactory::value_type> >::type* = 0)
00248 {
00249 }
00250
00251 template<class TypedInPlaceFactory>
00252 void optionally_setup_internal_weak_this_p(typename boost::enable_if<
00253 boost::is_base_of<
00254 enable_unintrusive_from_this<typename TypedInPlaceFactory::value_type>,
00255 typename TypedInPlaceFactory::value_type> >::type* = 0)
00256 {
00257 get()->_internal_weak_this = *this;
00258 }
00259
00260 void destroy_wrapper()
00261 {
00262 static_cast<T*>(static_cast<real_wrapper_t*>(m_wrapper)->stored_object())->~T();
00263
00264
00265
00266 static_cast<real_weak_wrapper_t*>
00267 (static_cast<real_wrapper_t*>(m_wrapper)->m_weak_wrapper)
00268 ->
00269 m_real_wrapper = NULL;
00270
00271 m_wrapper->destroy_self(m_wrapper);
00272 set_new_wrapper(detail::the_zero_wrapper());
00273 }
00274
00275 void decrement()
00276 {
00277 if(m_wrapper->decrement() == 0) {
00278 destroy_wrapper();
00279 return;
00280 }
00281 }
00282
00283 void set_new_wrapper(detail::count_wrapper_base* new_wrapper)
00284 {
00285 new_wrapper->increment();
00286 m_wrapper = new_wrapper;
00287 }
00288
00289 bool is_null() const
00290 {
00291 return m_wrapper == detail::the_zero_wrapper();
00292 }
00293
00294
00295 detail::count_wrapper_base* m_wrapper;
00296
00297 template<class Y>
00298 friend class unintrusive_ptr;
00299
00300 friend class weak_unintrusive_ptr<T>;
00301
00302 template<class Y>
00303 friend int detail::get_use_count(unintrusive_ptr<Y> const &x);
00304
00305 template<class Y>
00306 friend bool detail::get_unique(unintrusive_ptr<Y> const &x);
00307
00308 template<class X, class Y>
00309 friend unintrusive_ptr<X> static_pointer_cast(unintrusive_ptr<Y> const & r);
00310
00311 template<class X, class Y>
00312 friend unintrusive_ptr<X> const_pointer_cast(unintrusive_ptr<Y> const & r);
00313
00314 template<class X, class Y>
00315 friend unintrusive_ptr<X> dynamic_pointer_cast(unintrusive_ptr<Y> const & r);
00316
00317 template<class X, class Y>
00318 friend bool operator==(unintrusive_ptr<X> const & a, unintrusive_ptr<Y> const & b);
00319
00320 template<class X, class Y>
00321 friend bool operator!=(unintrusive_ptr<X> const & a, unintrusive_ptr<Y> const & b);
00322
00323 template<class X, class Y>
00324 friend bool operator<(unintrusive_ptr<X> const & a, unintrusive_ptr<Y> const & b);
00325 };
00326
00327 template<class X, class Y>
00328 bool operator==(unintrusive_ptr<X> const & a, unintrusive_ptr<Y> const & b)
00329 {
00330 return a.get() == b.get();
00331 }
00332
00333 template<class X, class Y>
00334 bool operator!=(unintrusive_ptr<X> const & a, unintrusive_ptr<Y> const & b)
00335 {
00336 return a.get() != b.get();
00337 }
00338
00339 template<class X, class Y>
00340 bool operator<(unintrusive_ptr<X> const & a, unintrusive_ptr<Y> const & b)
00341 {
00342 return a.m_wrapper < b.m_wrapper;
00343 }
00344
00345 template<class T>
00346 void swap(unintrusive_ptr<T> & a, unintrusive_ptr<T> & b)
00347 {
00348 a.swap(b);
00349 }
00350
00351 template<class T>
00352 T* get_pointer(unintrusive_ptr<T> const & p)
00353 {
00354 return p.get();
00355 }
00356
00357 template<class T, class U>
00358 unintrusive_ptr<T> static_pointer_cast(unintrusive_ptr<U> const & r)
00359 {
00360 (void)static_cast<T*>((U*)0);
00361 return unintrusive_ptr<T>(r.m_wrapper);
00362 }
00363
00364 template<class T, class U>
00365 unintrusive_ptr<T> const_pointer_cast(unintrusive_ptr<U> const & r)
00366 {
00367 (void)const_cast<T*>((U* const)0);
00368 return unintrusive_ptr<T>(r.m_wrapper);
00369 }
00370
00371 template<class T, class U>
00372 unintrusive_ptr<T> dynamic_pointer_cast(unintrusive_ptr<U> const & r)
00373 {
00374 if(dynamic_cast<T*>(r.get()))
00375 return unintrusive_ptr<T>(r);
00376
00377 return unintrusive_ptr<T>();
00378 }
00379
00382 }
00383
00384 #endif
00385