test_fss_dispatch.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // Copyright (C) 2001-2003
  2. // William E. Kempf
  3. // Copyright (C) 2007 Anthony Williams
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #include <iostream>
  8. #include <mutex>
  9. #include <boost/test/unit_test.hpp>
  10. #include <boost/fiber/all.hpp>
  11. boost::fibers::mutex check_mutex;
  12. boost::fibers::mutex fss_mutex;
  13. int fss_instances = 0;
  14. int fss_total = 0;
  15. struct fss_value_t {
  16. fss_value_t() {
  17. std::unique_lock<boost::fibers::mutex> lock(fss_mutex);
  18. ++fss_instances;
  19. ++fss_total;
  20. value = 0;
  21. }
  22. ~fss_value_t() {
  23. std::unique_lock<boost::fibers::mutex> lock(fss_mutex);
  24. --fss_instances;
  25. }
  26. int value;
  27. };
  28. boost::fibers::fiber_specific_ptr<fss_value_t> fss_value;
  29. void fss_fiber() {
  30. fss_value.reset(new fss_value_t());
  31. for (int i=0; i<1000; ++i) {
  32. int& n = fss_value->value;
  33. if (n != i) {
  34. std::unique_lock<boost::fibers::mutex> lock(check_mutex);
  35. BOOST_CHECK_EQUAL(n, i);
  36. }
  37. ++n;
  38. }
  39. }
  40. void fss() {
  41. fss_instances = 0;
  42. fss_total = 0;
  43. boost::fibers::fiber f1( boost::fibers::launch::dispatch, fss_fiber);
  44. boost::fibers::fiber f2( boost::fibers::launch::dispatch, fss_fiber);
  45. boost::fibers::fiber f3( boost::fibers::launch::dispatch, fss_fiber);
  46. boost::fibers::fiber f4( boost::fibers::launch::dispatch, fss_fiber);
  47. boost::fibers::fiber f5( boost::fibers::launch::dispatch, fss_fiber);
  48. f1.join();
  49. f2.join();
  50. f3.join();
  51. f4.join();
  52. f5.join();
  53. std::cout
  54. << "fss_instances = " << fss_instances
  55. << "; fss_total = " << fss_total
  56. << "\n";
  57. std::cout.flush();
  58. BOOST_CHECK_EQUAL(fss_instances, 0);
  59. BOOST_CHECK_EQUAL(fss_total, 5);
  60. }
  61. void test_fss() {
  62. boost::fibers::fiber( boost::fibers::launch::dispatch, fss).join();
  63. }
  64. bool fss_cleanup_called=false;
  65. struct Dummy {
  66. };
  67. void fss_custom_cleanup(Dummy* d) {
  68. delete d;
  69. fss_cleanup_called=true;
  70. }
  71. boost::fibers::fiber_specific_ptr<Dummy> fss_with_cleanup(fss_custom_cleanup);
  72. void fss_fiber_with_custom_cleanup() {
  73. fss_with_cleanup.reset(new Dummy);
  74. }
  75. void fss_with_custom_cleanup() {
  76. boost::fibers::fiber f( boost::fibers::launch::dispatch, fss_fiber_with_custom_cleanup);
  77. try {
  78. f.join();
  79. } catch(...) {
  80. f.join();
  81. throw;
  82. }
  83. BOOST_CHECK(fss_cleanup_called);
  84. }
  85. void test_fss_with_custom_cleanup() {
  86. boost::fibers::fiber( boost::fibers::launch::dispatch, fss_with_custom_cleanup).join();
  87. }
  88. Dummy* fss_object=new Dummy;
  89. void fss_fiber_with_custom_cleanup_and_release() {
  90. fss_with_cleanup.reset(fss_object);
  91. fss_with_cleanup.release();
  92. }
  93. void do_test_fss_does_no_cleanup_after_release() {
  94. fss_cleanup_called=false;
  95. boost::fibers::fiber f( boost::fibers::launch::dispatch, fss_fiber_with_custom_cleanup_and_release);
  96. try {
  97. f.join();
  98. } catch(...) {
  99. f.join();
  100. throw;
  101. }
  102. BOOST_CHECK(!fss_cleanup_called);
  103. if(!fss_cleanup_called) {
  104. delete fss_object;
  105. }
  106. }
  107. struct dummy_class_tracks_deletions {
  108. static unsigned deletions;
  109. ~dummy_class_tracks_deletions() {
  110. ++deletions;
  111. }
  112. };
  113. unsigned dummy_class_tracks_deletions::deletions=0;
  114. boost::fibers::fiber_specific_ptr<dummy_class_tracks_deletions> fss_with_null_cleanup(NULL);
  115. void fss_fiber_with_null_cleanup(dummy_class_tracks_deletions* delete_tracker) {
  116. fss_with_null_cleanup.reset(delete_tracker);
  117. }
  118. void do_test_fss_does_no_cleanup_with_null_cleanup_function() {
  119. dummy_class_tracks_deletions* delete_tracker=new dummy_class_tracks_deletions;
  120. boost::fibers::fiber f( boost::fibers::launch::dispatch, [&delete_tracker](){
  121. fss_fiber_with_null_cleanup( delete_tracker); });
  122. try {
  123. f.join();
  124. } catch(...) {
  125. f.join();
  126. throw;
  127. }
  128. BOOST_CHECK(!dummy_class_tracks_deletions::deletions);
  129. if(!dummy_class_tracks_deletions::deletions) {
  130. delete delete_tracker;
  131. }
  132. }
  133. void test_fss_does_no_cleanup_after_release() {
  134. boost::fibers::fiber( boost::fibers::launch::dispatch, do_test_fss_does_no_cleanup_after_release).join();
  135. }
  136. void test_fss_does_no_cleanup_with_null_cleanup_function() {
  137. boost::fibers::fiber( boost::fibers::launch::dispatch, do_test_fss_does_no_cleanup_with_null_cleanup_function).join();
  138. }
  139. void fiber_with_local_fss_ptr() {
  140. {
  141. boost::fibers::fiber_specific_ptr<Dummy> local_fss(fss_custom_cleanup);
  142. local_fss.reset(new Dummy);
  143. }
  144. BOOST_CHECK(fss_cleanup_called);
  145. fss_cleanup_called=false;
  146. }
  147. void fss_does_not_call_cleanup_after_ptr_destroyed() {
  148. boost::fibers::fiber( boost::fibers::launch::dispatch, fiber_with_local_fss_ptr).join();
  149. BOOST_CHECK(!fss_cleanup_called);
  150. }
  151. void test_fss_does_not_call_cleanup_after_ptr_destroyed() {
  152. boost::fibers::fiber( boost::fibers::launch::dispatch, fss_does_not_call_cleanup_after_ptr_destroyed).join();
  153. }
  154. void fss_cleanup_not_called_for_null_pointer() {
  155. boost::fibers::fiber_specific_ptr<Dummy> local_fss(fss_custom_cleanup);
  156. local_fss.reset(new Dummy);
  157. fss_cleanup_called=false;
  158. local_fss.reset(0);
  159. BOOST_CHECK(fss_cleanup_called);
  160. fss_cleanup_called=false;
  161. local_fss.reset(new Dummy);
  162. BOOST_CHECK(!fss_cleanup_called);
  163. }
  164. void test_fss_cleanup_not_called_for_null_pointer() {
  165. boost::fibers::fiber( boost::fibers::launch::dispatch, fss_cleanup_not_called_for_null_pointer).join();
  166. }
  167. void fss_at_the_same_adress() {
  168. for(int i=0; i<2; i++) {
  169. boost::fibers::fiber_specific_ptr<Dummy> local_fss(fss_custom_cleanup);
  170. local_fss.reset(new Dummy);
  171. fss_cleanup_called=false;
  172. BOOST_CHECK(fss_cleanup_called);
  173. fss_cleanup_called=false;
  174. BOOST_CHECK(!fss_cleanup_called);
  175. }
  176. }
  177. void test_fss_at_the_same_adress() {
  178. boost::fibers::fiber( boost::fibers::launch::dispatch, fss_at_the_same_adress).join();
  179. }
  180. boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) {
  181. boost::unit_test::test_suite* test =
  182. BOOST_TEST_SUITE("Boost.Fiber: fss test suite");
  183. test->add(BOOST_TEST_CASE(test_fss));
  184. test->add(BOOST_TEST_CASE(test_fss_with_custom_cleanup));
  185. test->add(BOOST_TEST_CASE(test_fss_does_no_cleanup_after_release));
  186. test->add(BOOST_TEST_CASE(test_fss_does_no_cleanup_with_null_cleanup_function));
  187. test->add(BOOST_TEST_CASE(test_fss_does_not_call_cleanup_after_ptr_destroyed));
  188. test->add(BOOST_TEST_CASE(test_fss_cleanup_not_called_for_null_pointer));
  189. return test;
  190. }