test_shared_mutex_part_2.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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_TEST_MODULE Boost.Threads: shared_mutex_part2 test suite
  7. #include <boost/test/unit_test.hpp>
  8. #include <boost/thread/thread.hpp>
  9. #include <boost/thread/xtime.hpp>
  10. #include "./util.inl"
  11. #include "./shared_mutex_locking_thread.hpp"
  12. #define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \
  13. { \
  14. boost::unique_lock<boost::mutex> lock(mutex_name); \
  15. BOOST_CHECK_EQUAL(value,expected_value); \
  16. }
  17. class simple_upgrade_thread
  18. {
  19. boost::shared_mutex& rwm;
  20. boost::mutex& finish_mutex;
  21. boost::mutex& unblocked_mutex;
  22. unsigned& unblocked_count;
  23. void operator=(simple_upgrade_thread&);
  24. public:
  25. simple_upgrade_thread(boost::shared_mutex& rwm_,
  26. boost::mutex& finish_mutex_,
  27. boost::mutex& unblocked_mutex_,
  28. unsigned& unblocked_count_):
  29. rwm(rwm_),finish_mutex(finish_mutex_),
  30. unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_)
  31. {}
  32. void operator()()
  33. {
  34. boost::upgrade_lock<boost::shared_mutex> lk(rwm);
  35. {
  36. boost::unique_lock<boost::mutex> ulk(unblocked_mutex);
  37. ++unblocked_count;
  38. }
  39. boost::unique_lock<boost::mutex> flk(finish_mutex);
  40. }
  41. };
  42. BOOST_AUTO_TEST_CASE(test_only_one_upgrade_lock_permitted)
  43. {
  44. unsigned const number_of_threads=2;
  45. boost::thread_group pool;
  46. boost::shared_mutex rw_mutex;
  47. unsigned unblocked_count=0;
  48. unsigned simultaneous_running_count=0;
  49. unsigned max_simultaneous_running=0;
  50. boost::mutex unblocked_count_mutex;
  51. boost::condition_variable unblocked_condition;
  52. boost::mutex finish_mutex;
  53. boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
  54. try
  55. {
  56. for(unsigned i=0;i<number_of_threads;++i)
  57. {
  58. pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
  59. finish_mutex,simultaneous_running_count,max_simultaneous_running));
  60. }
  61. boost::thread::sleep(delay(1));
  62. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U);
  63. finish_lock.unlock();
  64. pool.join_all();
  65. }
  66. catch(...)
  67. {
  68. pool.interrupt_all();
  69. pool.join_all();
  70. throw;
  71. }
  72. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads);
  73. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u);
  74. }
  75. BOOST_AUTO_TEST_CASE(test_can_lock_upgrade_if_currently_locked_shared)
  76. {
  77. boost::thread_group pool;
  78. boost::shared_mutex rw_mutex;
  79. unsigned unblocked_count=0;
  80. unsigned simultaneous_running_count=0;
  81. unsigned max_simultaneous_running=0;
  82. boost::mutex unblocked_count_mutex;
  83. boost::condition_variable unblocked_condition;
  84. boost::mutex finish_mutex;
  85. boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
  86. unsigned const reader_count=10;
  87. try
  88. {
  89. for(unsigned i=0;i<reader_count;++i)
  90. {
  91. pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
  92. finish_mutex,simultaneous_running_count,max_simultaneous_running));
  93. }
  94. boost::thread::sleep(delay(1));
  95. pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
  96. finish_mutex,simultaneous_running_count,max_simultaneous_running));
  97. {
  98. boost::unique_lock<boost::mutex> lk(unblocked_count_mutex);
  99. while(unblocked_count<(reader_count+1))
  100. {
  101. unblocked_condition.wait(lk);
  102. }
  103. }
  104. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1);
  105. finish_lock.unlock();
  106. pool.join_all();
  107. }
  108. catch(...)
  109. {
  110. pool.interrupt_all();
  111. pool.join_all();
  112. throw;
  113. }
  114. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1);
  115. CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count+1);
  116. }
  117. BOOST_AUTO_TEST_CASE(test_can_lock_upgrade_to_unique_if_currently_locked_upgrade)
  118. {
  119. boost::shared_mutex mtx;
  120. boost::upgrade_lock<boost::shared_mutex> l(mtx);
  121. boost::upgrade_to_unique_lock<boost::shared_mutex> ul(l);
  122. BOOST_CHECK(ul.owns_lock());
  123. }
  124. BOOST_AUTO_TEST_CASE(test_if_other_thread_has_write_lock_try_lock_shared_returns_false)
  125. {
  126. boost::shared_mutex rw_mutex;
  127. boost::mutex finish_mutex;
  128. boost::mutex unblocked_mutex;
  129. unsigned unblocked_count=0;
  130. boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
  131. boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
  132. boost::this_thread::sleep(boost::posix_time::seconds(1));
  133. CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
  134. bool const try_succeeded=rw_mutex.try_lock_shared();
  135. BOOST_CHECK(!try_succeeded);
  136. if(try_succeeded)
  137. {
  138. rw_mutex.unlock_shared();
  139. }
  140. finish_lock.unlock();
  141. writer.join();
  142. }
  143. BOOST_AUTO_TEST_CASE(test_if_other_thread_has_write_lock_try_lock_upgrade_returns_false)
  144. {
  145. boost::shared_mutex rw_mutex;
  146. boost::mutex finish_mutex;
  147. boost::mutex unblocked_mutex;
  148. unsigned unblocked_count=0;
  149. boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
  150. boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
  151. boost::this_thread::sleep(boost::posix_time::seconds(1));
  152. CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
  153. bool const try_succeeded=rw_mutex.try_lock_upgrade();
  154. BOOST_CHECK(!try_succeeded);
  155. if(try_succeeded)
  156. {
  157. rw_mutex.unlock_upgrade();
  158. }
  159. finish_lock.unlock();
  160. writer.join();
  161. }
  162. BOOST_AUTO_TEST_CASE(test_if_no_thread_has_lock_try_lock_shared_returns_true)
  163. {
  164. boost::shared_mutex rw_mutex;
  165. bool const try_succeeded=rw_mutex.try_lock_shared();
  166. BOOST_CHECK(try_succeeded);
  167. if(try_succeeded)
  168. {
  169. rw_mutex.unlock_shared();
  170. }
  171. }
  172. BOOST_AUTO_TEST_CASE(test_if_no_thread_has_lock_try_lock_upgrade_returns_true)
  173. {
  174. boost::shared_mutex rw_mutex;
  175. bool const try_succeeded=rw_mutex.try_lock_upgrade();
  176. BOOST_CHECK(try_succeeded);
  177. if(try_succeeded)
  178. {
  179. rw_mutex.unlock_upgrade();
  180. }
  181. }
  182. BOOST_AUTO_TEST_CASE(test_if_other_thread_has_shared_lock_try_lock_shared_returns_true)
  183. {
  184. boost::shared_mutex rw_mutex;
  185. boost::mutex finish_mutex;
  186. boost::mutex unblocked_mutex;
  187. unsigned unblocked_count=0;
  188. boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
  189. boost::thread writer(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
  190. boost::thread::sleep(delay(1));
  191. CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
  192. bool const try_succeeded=rw_mutex.try_lock_shared();
  193. BOOST_CHECK(try_succeeded);
  194. if(try_succeeded)
  195. {
  196. rw_mutex.unlock_shared();
  197. }
  198. finish_lock.unlock();
  199. writer.join();
  200. }
  201. BOOST_AUTO_TEST_CASE(test_if_other_thread_has_shared_lock_try_lock_upgrade_returns_true)
  202. {
  203. boost::shared_mutex rw_mutex;
  204. boost::mutex finish_mutex;
  205. boost::mutex unblocked_mutex;
  206. unsigned unblocked_count=0;
  207. boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
  208. boost::thread writer(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
  209. boost::thread::sleep(delay(1));
  210. CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
  211. bool const try_succeeded=rw_mutex.try_lock_upgrade();
  212. BOOST_CHECK(try_succeeded);
  213. if(try_succeeded)
  214. {
  215. rw_mutex.unlock_upgrade();
  216. }
  217. finish_lock.unlock();
  218. writer.join();
  219. }
  220. BOOST_AUTO_TEST_CASE(test_if_other_thread_has_upgrade_lock_try_lock_upgrade_returns_false)
  221. {
  222. boost::shared_mutex rw_mutex;
  223. boost::mutex finish_mutex;
  224. boost::mutex unblocked_mutex;
  225. unsigned unblocked_count=0;
  226. boost::unique_lock<boost::mutex> finish_lock(finish_mutex);
  227. boost::thread writer(simple_upgrade_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
  228. boost::this_thread::sleep(boost::posix_time::seconds(1));
  229. CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
  230. bool const try_succeeded=rw_mutex.try_lock_upgrade();
  231. BOOST_CHECK(!try_succeeded);
  232. if(try_succeeded)
  233. {
  234. rw_mutex.unlock_upgrade();
  235. }
  236. finish_lock.unlock();
  237. writer.join();
  238. }