/libs/thread/test/test_mutex.cpp

https://bitbucket.org/prenaux/boost_1_53 · C++ · 363 lines · 267 code · 68 blank · 28 comment · 0 complexity · 4fe960e47411733ebd39e6b5daee501f MD5 · raw file

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