test_shared_mutex.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. // (C) Copyright 2006-7 Anthony Williams
  2. // Distributed under the Boost Software License, Version 1.0. (See
  3. // accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. #define BOOST_THREAD_VERSION 2
  6. #define BOOST_THREAD_PROVIDES_INTERRUPTIONS
  7. #define BOOST_TEST_MODULE Boost.Threads: shared_mutex test suite
  8. #include <boost/test/unit_test.hpp>
  9. #include <boost/thread/thread.hpp>
  10. #include <boost/thread/xtime.hpp>
  11. #include "./util.inl"
  12. #include "./shared_mutex_locking_thread.hpp"
  13. #include <iostream>
  14. #define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \
  15. { \
  16. boost::unique_lock<boost::mutex> lock(mutex_name); \
  17. BOOST_CHECK_EQUAL(value,expected_value); \
  18. }
  19. BOOST_AUTO_TEST_CASE(test_multiple_readers)
  20. {
  21. std::cout << __LINE__ << std::endl;
  22. unsigned const number_of_threads=10;
  23. boost::thread_group pool;
  24. boost::shared_mutex rw_mutex;
  25. unsigned unblocked_count=0;
  26. unsigned simultaneous_running_count=0;
  27. unsigned max_simultaneous_running=0;
  28. boost::mutex unblocked_count_mutex;
  29. boost::condition_variable unblocked_condition;
  30. boost::mutex finish_mutex;
  31. boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
  32. try
  33. {
  34. for(unsigned i=0;i<number_of_threads;++i)
  35. {
  36. pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
  37. finish_mutex,simultaneous_running_count,max_simultaneous_running));
  38. }
  39. {
  40. boost::unique_lock<boost::mutex> lk(unblocked_count_mutex);
  41. while(unblocked_count<number_of_threads)
  42. {
  43. unblocked_condition.wait(lk);
  44. }
  45. }
  46. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads);
  47. finish_lock.unlock();
  48. pool.join_all();
  49. }
  50. catch(...)
  51. {
  52. pool.interrupt_all();
  53. pool.join_all();
  54. throw;
  55. }
  56. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,number_of_threads);
  57. }
  58. BOOST_AUTO_TEST_CASE(test_only_one_writer_permitted)
  59. {
  60. std::cout << __LINE__ << std::endl;
  61. unsigned const number_of_threads=10;
  62. boost::thread_group pool;
  63. boost::shared_mutex rw_mutex;
  64. unsigned unblocked_count=0;
  65. unsigned simultaneous_running_count=0;
  66. unsigned max_simultaneous_running=0;
  67. boost::mutex unblocked_count_mutex;
  68. boost::condition_variable unblocked_condition;
  69. boost::mutex finish_mutex;
  70. boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
  71. try
  72. {
  73. for(unsigned i=0;i<number_of_threads;++i)
  74. {
  75. pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
  76. finish_mutex,simultaneous_running_count,max_simultaneous_running));
  77. }
  78. boost::thread::sleep(delay(2));
  79. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U);
  80. finish_lock.unlock();
  81. pool.join_all();
  82. }
  83. catch(...)
  84. {
  85. pool.interrupt_all();
  86. pool.join_all();
  87. throw;
  88. }
  89. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads);
  90. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u);
  91. }
  92. BOOST_AUTO_TEST_CASE(test_reader_blocks_writer)
  93. {
  94. std::cout << __LINE__ << std::endl;
  95. boost::thread_group pool;
  96. boost::shared_mutex rw_mutex;
  97. unsigned unblocked_count=0;
  98. unsigned simultaneous_running_count=0;
  99. unsigned max_simultaneous_running=0;
  100. boost::mutex unblocked_count_mutex;
  101. boost::condition_variable unblocked_condition;
  102. boost::mutex finish_mutex;
  103. boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
  104. try
  105. {
  106. pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
  107. finish_mutex,simultaneous_running_count,max_simultaneous_running));
  108. {
  109. boost::unique_lock<boost::mutex> lk(unblocked_count_mutex);
  110. while(unblocked_count<1)
  111. {
  112. unblocked_condition.wait(lk);
  113. }
  114. }
  115. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U);
  116. pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
  117. finish_mutex,simultaneous_running_count,max_simultaneous_running));
  118. boost::thread::sleep(delay(1));
  119. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U);
  120. finish_lock.unlock();
  121. pool.join_all();
  122. }
  123. catch(...)
  124. {
  125. pool.interrupt_all();
  126. pool.join_all();
  127. throw;
  128. }
  129. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,2U);
  130. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u);
  131. }
  132. BOOST_AUTO_TEST_CASE(test_unlocking_writer_unblocks_all_readers)
  133. {
  134. std::cout << __LINE__ << std::endl;
  135. boost::thread_group pool;
  136. boost::shared_mutex rw_mutex;
  137. boost::unique_lock<boost::shared_mutex> write_lock(rw_mutex);
  138. unsigned unblocked_count=0;
  139. unsigned simultaneous_running_count=0;
  140. unsigned max_simultaneous_running=0;
  141. boost::mutex unblocked_count_mutex;
  142. boost::condition_variable unblocked_condition;
  143. boost::mutex finish_mutex;
  144. boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
  145. unsigned const reader_count=10;
  146. try
  147. {
  148. for(unsigned i=0;i<reader_count;++i)
  149. {
  150. pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
  151. finish_mutex,simultaneous_running_count,max_simultaneous_running));
  152. }
  153. boost::thread::sleep(delay(1));
  154. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,0U);
  155. write_lock.unlock();
  156. {
  157. boost::unique_lock<boost::mutex> lk(unblocked_count_mutex);
  158. while(unblocked_count<reader_count)
  159. {
  160. unblocked_condition.wait(lk);
  161. }
  162. }
  163. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count);
  164. finish_lock.unlock();
  165. pool.join_all();
  166. }
  167. catch(...)
  168. {
  169. pool.interrupt_all();
  170. pool.join_all();
  171. throw;
  172. }
  173. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count);
  174. }
  175. BOOST_AUTO_TEST_CASE(test_unlocking_last_reader_only_unblocks_one_writer)
  176. {
  177. std::cout << __LINE__ << std::endl;
  178. boost::thread_group pool;
  179. boost::shared_mutex rw_mutex;
  180. unsigned unblocked_count=0;
  181. unsigned simultaneous_running_readers=0;
  182. unsigned max_simultaneous_readers=0;
  183. unsigned simultaneous_running_writers=0;
  184. unsigned max_simultaneous_writers=0;
  185. boost::mutex unblocked_count_mutex;
  186. boost::condition_variable unblocked_condition;
  187. boost::mutex finish_reading_mutex;
  188. boost::unique_lock<boost::mutex> finish_reading_lock(finish_reading_mutex);
  189. boost::mutex finish_writing_mutex;
  190. boost::unique_lock<boost::mutex> finish_writing_lock(finish_writing_mutex);
  191. unsigned const reader_count=10;
  192. unsigned const writer_count=10;
  193. try
  194. {
  195. for(unsigned i=0;i<reader_count;++i)
  196. {
  197. pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
  198. finish_reading_mutex,simultaneous_running_readers,max_simultaneous_readers));
  199. }
  200. boost::thread::sleep(delay(1));
  201. for(unsigned i=0;i<writer_count;++i)
  202. {
  203. pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
  204. finish_writing_mutex,simultaneous_running_writers,max_simultaneous_writers));
  205. }
  206. {
  207. boost::unique_lock<boost::mutex> lk(unblocked_count_mutex);
  208. while(unblocked_count<reader_count)
  209. {
  210. unblocked_condition.wait(lk);
  211. }
  212. }
  213. boost::thread::sleep(delay(1));
  214. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count);
  215. finish_reading_lock.unlock();
  216. {
  217. boost::unique_lock<boost::mutex> lk(unblocked_count_mutex);
  218. while(unblocked_count<(reader_count+1))
  219. {
  220. unblocked_condition.wait(lk);
  221. }
  222. }
  223. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1);
  224. finish_writing_lock.unlock();
  225. pool.join_all();
  226. }
  227. catch(...)
  228. {
  229. pool.interrupt_all();
  230. pool.join_all();
  231. throw;
  232. }
  233. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+writer_count);
  234. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_readers,reader_count);
  235. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_writers,1u);
  236. }