enable_shared_from_this2.hpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #ifndef BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED
  2. #define BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED
  3. //
  4. // enable_shared_from_this2.hpp
  5. //
  6. // Copyright 2002, 2009 Peter Dimov
  7. // Copyright 2008 Frank Mori Hess
  8. //
  9. // Distributed under the Boost Software License, Version 1.0.
  10. // See accompanying file LICENSE_1_0.txt or copy at
  11. // http://www.boost.org/LICENSE_1_0.txt
  12. //
  13. #include <boost/config.hpp>
  14. #include <boost/shared_ptr.hpp>
  15. #include <boost/assert.hpp>
  16. #include <boost/detail/workaround.hpp>
  17. namespace boost
  18. {
  19. namespace detail
  20. {
  21. class esft2_deleter_wrapper
  22. {
  23. private:
  24. shared_ptr<void> deleter_;
  25. public:
  26. esft2_deleter_wrapper()
  27. {
  28. }
  29. template< class T > void set_deleter( shared_ptr<T> const & deleter )
  30. {
  31. deleter_ = deleter;
  32. }
  33. template< class T> void operator()( T* )
  34. {
  35. BOOST_ASSERT( deleter_.use_count() <= 1 );
  36. deleter_.reset();
  37. }
  38. };
  39. } // namespace detail
  40. template< class T > class enable_shared_from_this2
  41. {
  42. protected:
  43. enable_shared_from_this2()
  44. {
  45. }
  46. enable_shared_from_this2( enable_shared_from_this2 const & )
  47. {
  48. }
  49. enable_shared_from_this2 & operator=( enable_shared_from_this2 const & )
  50. {
  51. return *this;
  52. }
  53. ~enable_shared_from_this2()
  54. {
  55. BOOST_ASSERT( shared_this_.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist
  56. }
  57. private:
  58. mutable weak_ptr<T> weak_this_;
  59. mutable shared_ptr<T> shared_this_;
  60. public:
  61. shared_ptr<T> shared_from_this()
  62. {
  63. init_weak_once();
  64. return shared_ptr<T>( weak_this_ );
  65. }
  66. shared_ptr<T const> shared_from_this() const
  67. {
  68. init_weak_once();
  69. return shared_ptr<T>( weak_this_ );
  70. }
  71. private:
  72. void init_weak_once() const
  73. {
  74. if( weak_this_._empty() )
  75. {
  76. shared_this_.reset( static_cast< T* >( 0 ), detail::esft2_deleter_wrapper() );
  77. weak_this_ = shared_this_;
  78. }
  79. }
  80. public: // actually private, but avoids compiler template friendship issues
  81. // Note: invoked automatically by shared_ptr; do not call
  82. template<class X, class Y> void _internal_accept_owner( shared_ptr<X> * ppx, Y * py ) const
  83. {
  84. BOOST_ASSERT( ppx != 0 );
  85. if( weak_this_.use_count() == 0 )
  86. {
  87. weak_this_ = shared_ptr<T>( *ppx, py );
  88. }
  89. else if( shared_this_.use_count() != 0 )
  90. {
  91. BOOST_ASSERT( ppx->unique() ); // no weak_ptrs should exist either, but there's no way to check that
  92. detail::esft2_deleter_wrapper * pd = boost::get_deleter<detail::esft2_deleter_wrapper>( shared_this_ );
  93. BOOST_ASSERT( pd != 0 );
  94. pd->set_deleter( *ppx );
  95. ppx->reset( shared_this_, ppx->get() );
  96. shared_this_.reset();
  97. }
  98. }
  99. };
  100. } // namespace boost
  101. #endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED