shared_from_raw_test5.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. //
  2. // shared_from_raw_test5.cpp - was esft_constructor_test.cpp
  3. //
  4. // A test for calling shared_from_raw from constructors
  5. // (that is, prior to the object's ownership being passed to
  6. // an external shared_ptr).
  7. //
  8. // Copyright (c) 2008 Frank Mori Hess
  9. // Copyright (c) 2008 Peter Dimov
  10. //
  11. // Distributed under the Boost Software License, Version 1.0.
  12. //
  13. // See accompanying file LICENSE_1_0.txt or copy at
  14. // http://www.boost.org/LICENSE_1_0.txt)
  15. //
  16. #include <boost/smart_ptr/enable_shared_from_raw.hpp>
  17. #include <boost/shared_ptr.hpp>
  18. #include <boost/weak_ptr.hpp>
  19. #include <boost/detail/lightweight_test.hpp>
  20. #include <memory>
  21. class X: public boost::enable_shared_from_raw
  22. {
  23. private:
  24. int destroyed_;
  25. int deleted_;
  26. int expected_;
  27. private:
  28. X( X const& );
  29. X& operator=( X const& );
  30. public:
  31. static int instances;
  32. public:
  33. explicit X( int expected, boost::shared_ptr<X> *early_px = 0 ): destroyed_( 0 ), deleted_( 0 ), expected_( expected )
  34. {
  35. ++instances;
  36. if( early_px ) *early_px = shared_from_raw(this);
  37. }
  38. ~X()
  39. {
  40. BOOST_TEST( deleted_ == expected_ );
  41. BOOST_TEST( destroyed_ == 0 );
  42. ++destroyed_;
  43. --instances;
  44. }
  45. typedef void (*deleter_type)( X* );
  46. static void deleter( X * px )
  47. {
  48. ++px->deleted_;
  49. }
  50. static void deleter2( X * px )
  51. {
  52. ++px->deleted_;
  53. delete px;
  54. }
  55. };
  56. int X::instances = 0;
  57. template<typename T, typename U>
  58. bool are_shared_owners(const boost::shared_ptr<T> &a, const boost::shared_ptr<U> &b)
  59. {
  60. return !(a < b) && !(b < a);
  61. }
  62. struct Y: public boost::enable_shared_from_raw
  63. {};
  64. int main()
  65. {
  66. BOOST_TEST( X::instances == 0 );
  67. {
  68. boost::shared_ptr<X> early_px;
  69. X* x = new X( 1, &early_px );
  70. BOOST_TEST( early_px.use_count() > 0 );
  71. BOOST_TEST( boost::get_deleter<X::deleter_type>(early_px) == 0 );
  72. BOOST_TEST( early_px.get() == x );
  73. boost::shared_ptr<X> px( x, &X::deleter2 );
  74. BOOST_TEST( early_px.use_count() == 2 && px.use_count() == 2 );
  75. BOOST_TEST(are_shared_owners(early_px, px));
  76. px.reset();
  77. BOOST_TEST( early_px.use_count() == 1 );
  78. BOOST_TEST( X::instances == 1 );
  79. X::deleter_type *pd = boost::get_deleter<X::deleter_type>(early_px);
  80. BOOST_TEST(pd && *pd == &X::deleter2 );
  81. }
  82. BOOST_TEST( X::instances == 0 );
  83. {
  84. boost::shared_ptr<X> early_px;
  85. X* x = new X( 1, &early_px );
  86. boost::weak_ptr<X> early_weak_px = early_px;
  87. early_px.reset();
  88. BOOST_TEST( !early_weak_px.expired() );
  89. boost::shared_ptr<X> px( x, &X::deleter2 );
  90. BOOST_TEST( px.use_count() == 1 );
  91. BOOST_TEST( X::instances == 1 );
  92. BOOST_TEST(are_shared_owners(early_weak_px.lock(), px));
  93. px.reset();
  94. BOOST_TEST( early_weak_px.expired() );
  95. }
  96. BOOST_TEST( X::instances == 0 );
  97. {
  98. boost::shared_ptr<X> early_px;
  99. X x( 2, &early_px );
  100. BOOST_TEST( early_px.use_count() > 0 );
  101. boost::shared_ptr<X> px( &x, &X::deleter );
  102. BOOST_TEST( early_px.use_count() == 2 && px.use_count() == 2 );
  103. early_px.reset();
  104. BOOST_TEST( px.use_count() == 1 );
  105. BOOST_TEST( X::instances == 1 );
  106. px.reset();
  107. // test reinitialization after all shared_ptr have expired
  108. early_px = shared_from_raw(&x);
  109. px.reset( &x, &X::deleter );
  110. BOOST_TEST(are_shared_owners(early_px, px));
  111. early_px.reset();
  112. }
  113. BOOST_TEST( X::instances == 0 );
  114. {
  115. boost::weak_ptr<X> early_weak_px;
  116. {
  117. boost::shared_ptr<X> early_px;
  118. X x( 0, &early_px );
  119. early_weak_px = early_px;
  120. early_px.reset();
  121. BOOST_TEST( !early_weak_px.expired() );
  122. BOOST_TEST( X::instances == 1 );
  123. }
  124. BOOST_TEST( early_weak_px.expired() );
  125. }
  126. BOOST_TEST( X::instances == 0 );
  127. {
  128. boost::shared_ptr<Y> px(new Y());
  129. Y y(*px);
  130. px.reset();
  131. try
  132. {
  133. shared_from_raw(&y);
  134. }
  135. catch( const boost::bad_weak_ptr & )
  136. {
  137. BOOST_ERROR("y threw bad_weak_ptr");
  138. }
  139. }
  140. return boost::report_errors();
  141. }