test_condition_mt_dispatch.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright Oliver Kowalke 2013.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. //
  6. // This test is based on the tests of Boost.Thread
  7. #include <cstdio>
  8. #include <cstdlib>
  9. #include <iostream>
  10. #include <map>
  11. #include <mutex>
  12. #include <stdexcept>
  13. #include <vector>
  14. #include <boost/atomic.hpp>
  15. #include <boost/bind.hpp>
  16. #include <boost/chrono.hpp>
  17. #include <boost/cstdint.hpp>
  18. #include <boost/function.hpp>
  19. #include <boost/ref.hpp>
  20. #include <boost/test/unit_test.hpp>
  21. #include <boost/thread.hpp>
  22. #include <boost/utility.hpp>
  23. #include <boost/fiber/all.hpp>
  24. typedef boost::chrono::milliseconds ms;
  25. boost::atomic< int > value1;
  26. void wait_fn( boost::barrier & b,
  27. boost::fibers::mutex & mtx,
  28. boost::fibers::condition_variable & cond,
  29. bool & flag) {
  30. b.wait();
  31. std::unique_lock< boost::fibers::mutex > lk( mtx);
  32. cond.wait( lk, [&flag](){ return flag; });
  33. ++value1;
  34. }
  35. void notify_one_fn( boost::barrier & b,
  36. boost::fibers::mutex & mtx,
  37. boost::fibers::condition_variable & cond,
  38. bool & flag) {
  39. b.wait();
  40. std::unique_lock< boost::fibers::mutex > lk( mtx);
  41. flag = true;
  42. lk.unlock();
  43. cond.notify_one();
  44. }
  45. void notify_all_fn( boost::barrier & b,
  46. boost::fibers::mutex & mtx,
  47. boost::fibers::condition_variable & cond,
  48. bool & flag) {
  49. b.wait();
  50. std::unique_lock< boost::fibers::mutex > lk( mtx);
  51. flag = true;
  52. lk.unlock();
  53. cond.notify_all();
  54. }
  55. void fn1( boost::barrier & b,
  56. boost::fibers::mutex & mtx,
  57. boost::fibers::condition_variable & cond,
  58. bool & flag) {
  59. boost::fibers::fiber(
  60. boost::fibers::launch::dispatch,
  61. wait_fn,
  62. std::ref( b),
  63. std::ref( mtx),
  64. std::ref( cond),
  65. std::ref( flag) ).join();
  66. }
  67. void fn2( boost::barrier & b,
  68. boost::fibers::mutex & mtx,
  69. boost::fibers::condition_variable & cond,
  70. bool & flag) {
  71. boost::fibers::fiber(
  72. boost::fibers::launch::dispatch,
  73. notify_one_fn,
  74. std::ref( b),
  75. std::ref( mtx),
  76. std::ref( cond),
  77. std::ref( flag) ).join();
  78. }
  79. void fn3( boost::barrier & b,
  80. boost::fibers::mutex & mtx,
  81. boost::fibers::condition_variable & cond,
  82. bool & flag) {
  83. boost::fibers::fiber(
  84. boost::fibers::launch::dispatch,
  85. notify_all_fn,
  86. std::ref( b),
  87. std::ref( mtx),
  88. std::ref( cond),
  89. std::ref( flag) ).join();
  90. }
  91. void test_one_waiter_notify_one() {
  92. for ( int i = 0; i < 10; ++i) {
  93. boost::barrier b( 2);
  94. bool flag = false;
  95. value1 = 0;
  96. boost::fibers::mutex mtx;
  97. boost::fibers::condition_variable cond;
  98. BOOST_CHECK( 0 == value1);
  99. boost::thread t1(std::bind( fn1, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
  100. boost::thread t2(std::bind( fn2, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
  101. t1.join();
  102. t2.join();
  103. BOOST_CHECK( 1 == value1);
  104. }
  105. }
  106. void test_two_waiter_notify_all() {
  107. for ( int i = 0; i < 10; ++i) {
  108. boost::barrier b( 3);
  109. bool flag = false;
  110. value1 = 0;
  111. boost::fibers::mutex mtx;
  112. boost::fibers::condition_variable cond;
  113. BOOST_CHECK( 0 == value1);
  114. boost::thread t1(std::bind( fn1, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
  115. boost::thread t2(std::bind( fn1, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
  116. boost::thread t3(std::bind( fn3, std::ref( b), std::ref( mtx), std::ref( cond), std::ref( flag) ) );
  117. t1.join();
  118. t2.join();
  119. t3.join();
  120. BOOST_CHECK( 2 == value1);
  121. }
  122. }
  123. void test_dummy() {
  124. }
  125. boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
  126. {
  127. boost::unit_test::test_suite * test =
  128. BOOST_TEST_SUITE("Boost.Fiber: multithreaded condition_variable test suite");
  129. #if ! defined(BOOST_FIBERS_NO_ATOMICS)
  130. test->add( BOOST_TEST_CASE( & test_one_waiter_notify_one) );
  131. test->add( BOOST_TEST_CASE( & test_two_waiter_notify_all) );
  132. #else
  133. test->add( BOOST_TEST_CASE( & test_dummy) );
  134. #endif
  135. return test;
  136. }