test_mutex.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. // Copyright (C) 2001-2003
  2. // William E. Kempf
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #define BOOST_THREAD_VERSION 2
  7. #define BOOST_TEST_MODULE Boost.Threads: mutex test suite
  8. #include <boost/thread/detail/config.hpp>
  9. #include <boost/thread/mutex.hpp>
  10. #include <boost/thread/lock_types.hpp>
  11. #include <boost/thread/thread_only.hpp>
  12. #include <boost/thread/recursive_mutex.hpp>
  13. #include <boost/thread/thread_time.hpp>
  14. #include <boost/thread/condition.hpp>
  15. #define BOOST_TEST_MODULE Boost.Threads: mutex test suite
  16. #include <boost/test/unit_test.hpp>
  17. #define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_sleep_only
  18. #include "./util.inl"
  19. template <typename M>
  20. struct test_lock
  21. {
  22. typedef M mutex_type;
  23. typedef typename M::scoped_lock lock_type;
  24. void operator()()
  25. {
  26. mutex_type mutex;
  27. boost::condition condition;
  28. // Test the lock's constructors.
  29. {
  30. lock_type lock(mutex, boost::defer_lock);
  31. BOOST_CHECK(!lock);
  32. }
  33. lock_type lock(mutex);
  34. BOOST_CHECK(lock ? true : false);
  35. // Construct and initialize an xtime for a fast time out.
  36. boost::xtime xt = delay(0, 100);
  37. // Test the lock and the mutex with condition variables.
  38. // No one is going to notify this condition variable. We expect to
  39. // time out.
  40. BOOST_CHECK(!condition.timed_wait(lock, xt));
  41. BOOST_CHECK(lock ? true : false);
  42. // Test the lock and unlock methods.
  43. lock.unlock();
  44. BOOST_CHECK(!lock);
  45. lock.lock();
  46. BOOST_CHECK(lock ? true : false);
  47. }
  48. };
  49. template <typename M>
  50. struct test_trylock
  51. {
  52. typedef M mutex_type;
  53. typedef typename M::scoped_try_lock try_lock_type;
  54. void operator()()
  55. {
  56. mutex_type mutex;
  57. boost::condition condition;
  58. // Test the lock's constructors.
  59. {
  60. try_lock_type lock(mutex);
  61. BOOST_CHECK(lock ? true : false);
  62. }
  63. {
  64. try_lock_type lock(mutex, boost::defer_lock);
  65. BOOST_CHECK(!lock);
  66. }
  67. try_lock_type lock(mutex);
  68. BOOST_CHECK(lock ? true : false);
  69. // Construct and initialize an xtime for a fast time out.
  70. boost::xtime xt = delay(0, 100);
  71. // Test the lock and the mutex with condition variables.
  72. // No one is going to notify this condition variable. We expect to
  73. // time out.
  74. BOOST_CHECK(!condition.timed_wait(lock, xt));
  75. BOOST_CHECK(lock ? true : false);
  76. // Test the lock, unlock and trylock methods.
  77. lock.unlock();
  78. BOOST_CHECK(!lock);
  79. lock.lock();
  80. BOOST_CHECK(lock ? true : false);
  81. lock.unlock();
  82. BOOST_CHECK(!lock);
  83. BOOST_CHECK(lock.try_lock());
  84. BOOST_CHECK(lock ? true : false);
  85. }
  86. };
  87. template<typename Mutex>
  88. struct test_lock_times_out_if_other_thread_has_lock
  89. {
  90. typedef boost::unique_lock<Mutex> Lock;
  91. Mutex m;
  92. boost::mutex done_mutex;
  93. bool done;
  94. bool locked;
  95. boost::condition_variable done_cond;
  96. test_lock_times_out_if_other_thread_has_lock():
  97. done(false),locked(false)
  98. {}
  99. void locking_thread()
  100. {
  101. Lock lock(m,boost::defer_lock);
  102. lock.timed_lock(boost::posix_time::milliseconds(50));
  103. boost::lock_guard<boost::mutex> lk(done_mutex);
  104. locked=lock.owns_lock();
  105. done=true;
  106. done_cond.notify_one();
  107. }
  108. void locking_thread_through_constructor()
  109. {
  110. Lock lock(m,boost::posix_time::milliseconds(50));
  111. boost::lock_guard<boost::mutex> lk(done_mutex);
  112. locked=lock.owns_lock();
  113. done=true;
  114. done_cond.notify_one();
  115. }
  116. bool is_done() const
  117. {
  118. return done;
  119. }
  120. typedef test_lock_times_out_if_other_thread_has_lock<Mutex> this_type;
  121. void do_test(void (this_type::*test_func)())
  122. {
  123. Lock lock(m);
  124. locked=false;
  125. done=false;
  126. boost::thread t(test_func,this);
  127. try
  128. {
  129. {
  130. boost::unique_lock<boost::mutex> lk(done_mutex);
  131. BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2),
  132. boost::bind(&this_type::is_done,this)));
  133. BOOST_CHECK(!locked);
  134. }
  135. lock.unlock();
  136. t.join();
  137. }
  138. catch(...)
  139. {
  140. lock.unlock();
  141. t.join();
  142. throw;
  143. }
  144. }
  145. void operator()()
  146. {
  147. do_test(&this_type::locking_thread);
  148. do_test(&this_type::locking_thread_through_constructor);
  149. }
  150. };
  151. template <typename M>
  152. struct test_timedlock
  153. {
  154. typedef M mutex_type;
  155. typedef typename M::scoped_timed_lock timed_lock_type;
  156. static bool fake_predicate()
  157. {
  158. return false;
  159. }
  160. void operator()()
  161. {
  162. test_lock_times_out_if_other_thread_has_lock<mutex_type>()();
  163. mutex_type mutex;
  164. boost::condition condition;
  165. // Test the lock's constructors.
  166. {
  167. // Construct and initialize an xtime for a fast time out.
  168. boost::system_time xt = boost::get_system_time()+boost::posix_time::milliseconds(100);
  169. timed_lock_type lock(mutex, xt);
  170. BOOST_CHECK(lock ? true : false);
  171. }
  172. {
  173. timed_lock_type lock(mutex, boost::defer_lock);
  174. BOOST_CHECK(!lock);
  175. }
  176. timed_lock_type lock(mutex);
  177. BOOST_CHECK(lock ? true : false);
  178. // Construct and initialize an xtime for a fast time out.
  179. boost::system_time timeout = boost::get_system_time()+boost::posix_time::milliseconds(100);
  180. // Test the lock and the mutex with condition variables.
  181. // No one is going to notify this condition variable. We expect to
  182. // time out.
  183. BOOST_CHECK(!condition.timed_wait(lock, timeout, fake_predicate));
  184. BOOST_CHECK(lock ? true : false);
  185. boost::system_time now=boost::get_system_time();
  186. boost::posix_time::milliseconds const timeout_resolution(20);
  187. BOOST_CHECK((timeout-timeout_resolution)<now);
  188. // Test the lock, unlock and timedlock methods.
  189. lock.unlock();
  190. BOOST_CHECK(!lock);
  191. lock.lock();
  192. BOOST_CHECK(lock ? true : false);
  193. lock.unlock();
  194. BOOST_CHECK(!lock);
  195. boost::system_time target = boost::get_system_time()+boost::posix_time::milliseconds(100);
  196. BOOST_CHECK(lock.timed_lock(target));
  197. BOOST_CHECK(lock ? true : false);
  198. lock.unlock();
  199. BOOST_CHECK(!lock);
  200. BOOST_CHECK(mutex.timed_lock(boost::posix_time::milliseconds(100)));
  201. mutex.unlock();
  202. BOOST_CHECK(lock.timed_lock(boost::posix_time::milliseconds(100)));
  203. BOOST_CHECK(lock ? true : false);
  204. lock.unlock();
  205. BOOST_CHECK(!lock);
  206. }
  207. };
  208. template <typename M>
  209. struct test_recursive_lock
  210. {
  211. typedef M mutex_type;
  212. typedef typename M::scoped_lock lock_type;
  213. void operator()()
  214. {
  215. mutex_type mx;
  216. lock_type lock1(mx);
  217. lock_type lock2(mx);
  218. }
  219. };
  220. void do_test_mutex()
  221. {
  222. test_lock<boost::mutex>()();
  223. }
  224. BOOST_AUTO_TEST_CASE(test_mutex)
  225. {
  226. timed_test(&do_test_mutex, 3);
  227. }
  228. void do_test_try_mutex()
  229. {
  230. test_lock<boost::try_mutex>()();
  231. test_trylock<boost::try_mutex>()();
  232. }
  233. BOOST_AUTO_TEST_CASE(test_try_mutex)
  234. {
  235. timed_test(&do_test_try_mutex, 3);
  236. }
  237. void do_test_timed_mutex()
  238. {
  239. test_lock<boost::timed_mutex>()();
  240. test_trylock<boost::timed_mutex>()();
  241. test_timedlock<boost::timed_mutex>()();
  242. }
  243. BOOST_AUTO_TEST_CASE(test_timed_mutex)
  244. {
  245. timed_test(&do_test_timed_mutex, 3);
  246. }
  247. void do_test_recursive_mutex()
  248. {
  249. test_lock<boost::recursive_mutex>()();
  250. test_recursive_lock<boost::recursive_mutex>()();
  251. }
  252. BOOST_AUTO_TEST_CASE(test_recursive_mutex)
  253. {
  254. timed_test(&do_test_recursive_mutex, 3);
  255. }
  256. void do_test_recursive_try_mutex()
  257. {
  258. test_lock<boost::recursive_try_mutex>()();
  259. test_trylock<boost::recursive_try_mutex>()();
  260. test_recursive_lock<boost::recursive_try_mutex>()();
  261. }
  262. BOOST_AUTO_TEST_CASE(test_recursive_try_mutex)
  263. {
  264. timed_test(&do_test_recursive_try_mutex, 3);
  265. }
  266. void do_test_recursive_timed_mutex()
  267. {
  268. test_lock<boost::recursive_timed_mutex>()();
  269. test_trylock<boost::recursive_timed_mutex>()();
  270. test_timedlock<boost::recursive_timed_mutex>()();
  271. test_recursive_lock<boost::recursive_timed_mutex>()();
  272. }
  273. BOOST_AUTO_TEST_CASE(test_recursive_timed_mutex)
  274. {
  275. timed_test(&do_test_recursive_timed_mutex, 3);
  276. }