sharable_mutex_test_template.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. // Copyright (C) 2001-2003
  2. // William E. Kempf
  3. //
  4. // Permission to use, copy, modify, distribute and sell this software
  5. // and its documentation for any purpose is hereby granted without fee,
  6. // provided that the above copyright notice appear in all copies and
  7. // that both that copyright notice and this permission notice appear
  8. // in supporting documentation. William E. Kempf makes no representations
  9. // about the suitability of this software for any purpose.
  10. // It is provided "as is" without express or implied warranty.
  11. //////////////////////////////////////////////////////////////////////////////
  12. //
  13. // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
  14. // Software License, Version 1.0. (See accompanying file
  15. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  16. //
  17. // See http://www.boost.org/libs/interprocess for documentation.
  18. //
  19. //////////////////////////////////////////////////////////////////////////////
  20. #ifndef BOOST_INTERPROCESS_TEST_SHARABLE_MUTEX_TEST_TEMPLATE_HEADER
  21. #define BOOST_INTERPROCESS_TEST_SHARABLE_MUTEX_TEST_TEMPLATE_HEADER
  22. #include <boost/interprocess/detail/config_begin.hpp>
  23. #include <boost/interprocess/detail/workaround.hpp>
  24. #include <boost/interprocess/detail/os_thread_functions.hpp>
  25. #include "boost_interprocess_check.hpp"
  26. #include <boost/date_time/posix_time/posix_time_types.hpp>
  27. #include <boost/interprocess/sync/sharable_lock.hpp>
  28. #include <boost/interprocess/sync/scoped_lock.hpp>
  29. #include <iostream>
  30. #include <cassert>
  31. #include "util.hpp"
  32. namespace boost { namespace interprocess { namespace test {
  33. template<typename SM>
  34. void plain_exclusive(void *arg, SM &sm)
  35. {
  36. data<SM> *pdata = static_cast<data<SM>*>(arg);
  37. boost::interprocess::scoped_lock<SM> l(sm);
  38. boost::interprocess::ipcdetail::thread_sleep((1000*3*BaseSeconds));
  39. shared_val += 10;
  40. pdata->m_value = shared_val;
  41. }
  42. template<typename SM>
  43. void plain_shared(void *arg, SM &sm)
  44. {
  45. data<SM> *pdata = static_cast<data<SM>*>(arg);
  46. boost::interprocess::sharable_lock<SM> l(sm);
  47. if(pdata->m_secs){
  48. boost::interprocess::ipcdetail::thread_sleep((1000*pdata->m_secs*BaseSeconds));
  49. }
  50. pdata->m_value = shared_val;
  51. }
  52. template<typename SM>
  53. void try_exclusive(void *arg, SM &sm)
  54. {
  55. data<SM> *pdata = static_cast<data<SM>*>(arg);
  56. boost::interprocess::scoped_lock<SM> l(sm, boost::interprocess::defer_lock);
  57. if (l.try_lock()){
  58. boost::interprocess::ipcdetail::thread_sleep((1000*3*BaseSeconds));
  59. shared_val += 10;
  60. pdata->m_value = shared_val;
  61. }
  62. }
  63. template<typename SM>
  64. void try_shared(void *arg, SM &sm)
  65. {
  66. data<SM> *pdata = static_cast<data<SM>*>(arg);
  67. boost::interprocess::sharable_lock<SM> l(sm, boost::interprocess::defer_lock);
  68. if (l.try_lock()){
  69. if(pdata->m_secs){
  70. boost::interprocess::ipcdetail::thread_sleep((1000*pdata->m_secs*BaseSeconds));
  71. }
  72. pdata->m_value = shared_val;
  73. }
  74. }
  75. template<typename SM>
  76. void timed_exclusive(void *arg, SM &sm)
  77. {
  78. data<SM> *pdata = static_cast<data<SM>*>(arg);
  79. boost::posix_time::ptime pt(delay(pdata->m_secs));
  80. boost::interprocess::scoped_lock<SM>
  81. l (sm, boost::interprocess::defer_lock);
  82. if (l.timed_lock(pt)){
  83. boost::interprocess::ipcdetail::thread_sleep((1000*3*BaseSeconds));
  84. shared_val += 10;
  85. pdata->m_value = shared_val;
  86. }
  87. }
  88. template<typename SM>
  89. void timed_shared(void *arg, SM &sm)
  90. {
  91. data<SM> *pdata = static_cast<data<SM>*>(arg);
  92. boost::posix_time::ptime pt(delay(pdata->m_secs));
  93. boost::interprocess::sharable_lock<SM>
  94. l(sm, boost::interprocess::defer_lock);
  95. if (l.timed_lock(pt)){
  96. if(pdata->m_secs){
  97. boost::interprocess::ipcdetail::thread_sleep((1000*pdata->m_secs*BaseSeconds));
  98. }
  99. pdata->m_value = shared_val;
  100. }
  101. }
  102. template<typename SM>
  103. void test_plain_sharable_mutex()
  104. {
  105. {
  106. shared_val = 0;
  107. SM mtx;
  108. data<SM> s1(1);
  109. data<SM> s2(2);
  110. data<SM> e1(1);
  111. data<SM> e2(2);
  112. // Writer one launches, holds the lock for 3*BaseSeconds seconds.
  113. boost::interprocess::ipcdetail::OS_thread_t tw1;
  114. boost::interprocess::ipcdetail::thread_launch(tw1, thread_adapter<SM>(plain_exclusive, &e1, mtx));
  115. // Writer two launches, tries to grab the lock, "clearly"
  116. // after Writer one will already be holding it.
  117. boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds));
  118. boost::interprocess::ipcdetail::OS_thread_t tw2;
  119. boost::interprocess::ipcdetail::thread_launch(tw2, thread_adapter<SM>(plain_exclusive, &e2, mtx));
  120. // Reader one launches, "clearly" after writer two, and "clearly"
  121. // while writer 1 still holds the lock
  122. boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds));
  123. boost::interprocess::ipcdetail::OS_thread_t thr1;
  124. boost::interprocess::ipcdetail::thread_launch(thr1, thread_adapter<SM>(plain_shared,&s1, mtx));
  125. boost::interprocess::ipcdetail::OS_thread_t thr2;
  126. boost::interprocess::ipcdetail::thread_launch(thr2, thread_adapter<SM>(plain_shared,&s2, mtx));
  127. boost::interprocess::ipcdetail::thread_join(thr2);
  128. boost::interprocess::ipcdetail::thread_join(thr1);
  129. boost::interprocess::ipcdetail::thread_join(tw2);
  130. boost::interprocess::ipcdetail::thread_join(tw1);
  131. //We can only assure that the writer will be first
  132. BOOST_INTERPROCESS_CHECK(e1.m_value == 10);
  133. //A that we will execute all
  134. BOOST_INTERPROCESS_CHECK(s1.m_value == 20 || s2.m_value == 20 || e2.m_value == 20);
  135. }
  136. {
  137. shared_val = 0;
  138. SM mtx;
  139. data<SM> s1(1, 3);
  140. data<SM> s2(2, 3);
  141. data<SM> e1(1);
  142. data<SM> e2(2);
  143. //We launch 2 readers, that will block for 3*BaseTime seconds
  144. boost::interprocess::ipcdetail::OS_thread_t thr1;
  145. boost::interprocess::ipcdetail::thread_launch(thr1, thread_adapter<SM>(plain_shared,&s1, mtx));
  146. boost::interprocess::ipcdetail::OS_thread_t thr2;
  147. boost::interprocess::ipcdetail::thread_launch(thr2, thread_adapter<SM>(plain_shared,&s2, mtx));
  148. //Make sure they try to hold the sharable lock
  149. boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds));
  150. // We launch two writers, that should block until the readers end
  151. boost::interprocess::ipcdetail::OS_thread_t tw1;
  152. boost::interprocess::ipcdetail::thread_launch(tw1, thread_adapter<SM>(plain_exclusive,&e1, mtx));
  153. boost::interprocess::ipcdetail::OS_thread_t tw2;
  154. boost::interprocess::ipcdetail::thread_launch(tw2, thread_adapter<SM>(plain_exclusive,&e2, mtx));
  155. boost::interprocess::ipcdetail::thread_join(thr2);
  156. boost::interprocess::ipcdetail::thread_join(thr1);
  157. boost::interprocess::ipcdetail::thread_join(tw2);
  158. boost::interprocess::ipcdetail::thread_join(tw1);
  159. //We can only assure that the shared will finish first...
  160. BOOST_INTERPROCESS_CHECK(s1.m_value == 0 || s2.m_value == 0);
  161. //...and writers will be mutually excluded after readers
  162. BOOST_INTERPROCESS_CHECK((e1.m_value == 10 && e2.m_value == 20) ||
  163. (e1.m_value == 20 && e2.m_value == 10) );
  164. }
  165. }
  166. template<typename SM>
  167. void test_try_sharable_mutex()
  168. {
  169. SM mtx;
  170. data<SM> s1(1);
  171. data<SM> e1(2);
  172. data<SM> e2(3);
  173. // We start with some specialized tests for "try" behavior
  174. shared_val = 0;
  175. // Writer one launches, holds the lock for 3*BaseSeconds seconds.
  176. boost::interprocess::ipcdetail::OS_thread_t tw1;
  177. boost::interprocess::ipcdetail::thread_launch(tw1, thread_adapter<SM>(try_exclusive,&e1,mtx));
  178. // Reader one launches, "clearly" after writer #1 holds the lock
  179. // and before it releases the lock.
  180. boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds));
  181. boost::interprocess::ipcdetail::OS_thread_t thr1;
  182. boost::interprocess::ipcdetail::thread_launch(thr1, thread_adapter<SM>(try_shared,&s1,mtx));
  183. // Writer two launches in the same timeframe.
  184. boost::interprocess::ipcdetail::OS_thread_t tw2;
  185. boost::interprocess::ipcdetail::thread_launch(tw2, thread_adapter<SM>(try_exclusive,&e2,mtx));
  186. boost::interprocess::ipcdetail::thread_join(tw2);
  187. boost::interprocess::ipcdetail::thread_join(thr1);
  188. boost::interprocess::ipcdetail::thread_join(tw1);
  189. BOOST_INTERPROCESS_CHECK(e1.m_value == 10);
  190. BOOST_INTERPROCESS_CHECK(s1.m_value == -1); // Try would return w/o waiting
  191. BOOST_INTERPROCESS_CHECK(e2.m_value == -1); // Try would return w/o waiting
  192. }
  193. template<typename SM>
  194. void test_timed_sharable_mutex()
  195. {
  196. SM mtx;
  197. data<SM> s1(1,1*BaseSeconds);
  198. data<SM> s2(2,3*BaseSeconds);
  199. data<SM> e1(3,3*BaseSeconds);
  200. data<SM> e2(4,1*BaseSeconds);
  201. // We begin with some specialized tests for "timed" behavior
  202. shared_val = 0;
  203. // Writer one will hold the lock for 3*BaseSeconds seconds.
  204. boost::interprocess::ipcdetail::OS_thread_t tw1;
  205. boost::interprocess::ipcdetail::thread_launch(tw1, thread_adapter<SM>(timed_exclusive,&e1,mtx));
  206. boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds));
  207. // Writer two will "clearly" try for the lock after the readers
  208. // have tried for it. Writer will wait up 1*BaseSeconds seconds for the lock.
  209. // This write will fail.
  210. boost::interprocess::ipcdetail::OS_thread_t tw2;
  211. boost::interprocess::ipcdetail::thread_launch(tw2, thread_adapter<SM>(timed_exclusive,&e2,mtx));
  212. // Readers one and two will "clearly" try for the lock after writer
  213. // one already holds it. 1st reader will wait 1*BaseSeconds seconds, and will fail
  214. // to get the lock. 2nd reader will wait 3*BaseSeconds seconds, and will get
  215. // the lock.
  216. boost::interprocess::ipcdetail::OS_thread_t thr1;
  217. boost::interprocess::ipcdetail::thread_launch(thr1, thread_adapter<SM>(timed_shared,&s1,mtx));
  218. boost::interprocess::ipcdetail::OS_thread_t thr2;
  219. boost::interprocess::ipcdetail::thread_launch(thr2, thread_adapter<SM>(timed_shared,&s2,mtx));
  220. boost::interprocess::ipcdetail::thread_join(tw1);
  221. boost::interprocess::ipcdetail::thread_join(thr1);
  222. boost::interprocess::ipcdetail::thread_join(thr2);
  223. boost::interprocess::ipcdetail::thread_join(tw2);
  224. BOOST_INTERPROCESS_CHECK(e1.m_value == 10);
  225. BOOST_INTERPROCESS_CHECK(s1.m_value == -1);
  226. BOOST_INTERPROCESS_CHECK(s2.m_value == 10);
  227. BOOST_INTERPROCESS_CHECK(e2.m_value == -1);
  228. }
  229. template<typename SM>
  230. void test_all_sharable_mutex()
  231. {
  232. std::cout << "test_plain_sharable_mutex<" << typeid(SM).name() << ">" << std::endl;
  233. test_plain_sharable_mutex<SM>();
  234. std::cout << "test_try_sharable_mutex<" << typeid(SM).name() << ">" << std::endl;
  235. test_try_sharable_mutex<SM>();
  236. std::cout << "test_timed_sharable_mutex<" << typeid(SM).name() << ">" << std::endl;
  237. test_timed_sharable_mutex<SM>();
  238. }
  239. }}} //namespace boost { namespace interprocess { namespace test {
  240. #include <boost/interprocess/detail/config_end.hpp>
  241. #endif //#ifndef BOOST_INTERPROCESS_TEST_SHARABLE_MUTEX_TEST_TEMPLATE_HEADER