4.cc 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. // { dg-do run }
  2. // { dg-additional-options "-pthread" { target pthread } }
  3. // { dg-require-effective-target c++11 }
  4. // { dg-require-gthreads "" }
  5. // Copyright (C) 2010-2022 Free Software Foundation, Inc.
  6. //
  7. // This file is part of the GNU ISO C++ Library. This library is free
  8. // software; you can redistribute it and/or modify it under the
  9. // terms of the GNU General Public License as published by the
  10. // Free Software Foundation; either version 3, or (at your option)
  11. // any later version.
  12. // This library is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. // GNU General Public License for more details.
  16. // You should have received a copy of the GNU General Public License along
  17. // with this library; see the file COPYING3. If not see
  18. // <http://www.gnu.org/licenses/>.
  19. #include <mutex>
  20. #include <testsuite_hooks.h>
  21. struct unreliable_lock
  22. {
  23. std::mutex m;
  24. std::unique_lock<std::mutex> l;
  25. static int count;
  26. static int throw_on;
  27. static int lock_on;
  28. unreliable_lock() : l(m, std::defer_lock) { }
  29. ~unreliable_lock()
  30. {
  31. VERIFY( !l.owns_lock() );
  32. }
  33. void lock()
  34. {
  35. if (count == throw_on)
  36. throw throw_on;
  37. ++count;
  38. l.lock();
  39. }
  40. bool try_lock()
  41. {
  42. if (count == throw_on)
  43. throw throw_on;
  44. std::unique_lock<std::mutex> l2(m, std::defer_lock);
  45. if (count == lock_on)
  46. l2.lock();
  47. ++count;
  48. return l.try_lock();
  49. }
  50. void unlock()
  51. {
  52. VERIFY( l.owns_lock() );
  53. l.unlock();
  54. }
  55. };
  56. int unreliable_lock::count = 0;
  57. int unreliable_lock::throw_on = -1;
  58. int unreliable_lock::lock_on = -1;
  59. void test01()
  60. {
  61. unreliable_lock l1, l2, l3;
  62. std::mutex m1, m2, m3;
  63. try
  64. {
  65. unreliable_lock::count = 0;
  66. std::lock(l1, l2, l3);
  67. VERIFY( unreliable_lock::count == 3 );
  68. l1.unlock();
  69. l2.unlock();
  70. l3.unlock();
  71. }
  72. catch (...)
  73. {
  74. VERIFY( false );
  75. }
  76. // Repeat with non-heterogeneous arguments
  77. try
  78. {
  79. unreliable_lock::count = 0;
  80. std::lock(l1, l2, l3, m1);
  81. VERIFY( unreliable_lock::count == 3 );
  82. l1.unlock();
  83. l2.unlock();
  84. l3.unlock();
  85. VERIFY( !m1.try_lock() ); // already locked
  86. m1.unlock();
  87. }
  88. catch (...)
  89. {
  90. VERIFY( false );
  91. }
  92. try
  93. {
  94. unreliable_lock::count = 0;
  95. std::lock(m1, l1, l2, l3);
  96. VERIFY( unreliable_lock::count == 3 );
  97. VERIFY( !m1.try_lock() ); // already locked
  98. m1.unlock();
  99. l1.unlock();
  100. l2.unlock();
  101. l3.unlock();
  102. }
  103. catch (...)
  104. {
  105. VERIFY( false );
  106. }
  107. try
  108. {
  109. unreliable_lock::count = 0;
  110. std::lock(l1, m1, l2, m2, l3, m3);
  111. VERIFY( unreliable_lock::count == 3 );
  112. l1.unlock();
  113. l2.unlock();
  114. l3.unlock();
  115. VERIFY( !m1.try_lock() ); // already locked
  116. VERIFY( !m2.try_lock() ); // already locked
  117. VERIFY( !m3.try_lock() ); // already locked
  118. m1.unlock();
  119. m2.unlock();
  120. m3.unlock();
  121. }
  122. catch (...)
  123. {
  124. VERIFY( false );
  125. }
  126. }
  127. void test02()
  128. {
  129. // test behaviour when a lock is already held
  130. try
  131. {
  132. unreliable_lock::lock_on = 1;
  133. while (unreliable_lock::lock_on < 3)
  134. {
  135. unreliable_lock::count = 0;
  136. unreliable_lock l1, l2, l3;
  137. std::lock(l1, l2, l3);
  138. VERIFY( unreliable_lock::count > 3 );
  139. l1.unlock();
  140. l2.unlock();
  141. l3.unlock();
  142. ++unreliable_lock::lock_on;
  143. }
  144. }
  145. catch (...)
  146. {
  147. VERIFY( false );
  148. }
  149. // Repeat with non-heterogeneous arguments
  150. try
  151. {
  152. unreliable_lock::lock_on = 1;
  153. while (unreliable_lock::lock_on < 3)
  154. {
  155. unreliable_lock::count = 0;
  156. unreliable_lock l1, l2, l3;
  157. std::mutex m1;
  158. std::lock(l1, l2, l3, m1);
  159. VERIFY( unreliable_lock::count > 3 );
  160. l1.unlock();
  161. l2.unlock();
  162. l3.unlock();
  163. VERIFY( !m1.try_lock() ); // already locked
  164. m1.unlock();
  165. ++unreliable_lock::lock_on;
  166. }
  167. }
  168. catch (...)
  169. {
  170. VERIFY( false );
  171. }
  172. }
  173. void test03()
  174. {
  175. // test behaviour when an exception is thrown
  176. unreliable_lock::throw_on = 0;
  177. while (unreliable_lock::throw_on < 3)
  178. {
  179. unreliable_lock::count = 0;
  180. unreliable_lock l1, l2, l3;
  181. bool test = false;
  182. try
  183. {
  184. std::lock(l1, l2, l3);
  185. }
  186. catch (...)
  187. {
  188. test = true;
  189. }
  190. VERIFY( test );
  191. ++unreliable_lock::throw_on;
  192. }
  193. // Repeat with non-heterogeneous arguments
  194. unreliable_lock::throw_on = 0;
  195. while (unreliable_lock::throw_on < 3)
  196. {
  197. unreliable_lock::count = 0;
  198. unreliable_lock l1, l2, l3;
  199. std::mutex m1;
  200. bool test = false;
  201. try
  202. {
  203. std::lock(l1, l2, l3, m1);
  204. }
  205. catch (...)
  206. {
  207. test = true;
  208. }
  209. VERIFY( test );
  210. VERIFY( m1.try_lock() ); // m1 was not left locked by failed std::lock
  211. m1.unlock();
  212. ++unreliable_lock::throw_on;
  213. }
  214. unreliable_lock::throw_on = 0;
  215. while (unreliable_lock::throw_on < 3)
  216. {
  217. unreliable_lock::count = 0;
  218. unreliable_lock l1, l2, l3;
  219. std::mutex m1;
  220. bool test = false;
  221. try
  222. {
  223. std::lock(m1, l1, l2, l3);
  224. }
  225. catch (...)
  226. {
  227. test = true;
  228. }
  229. VERIFY( test );
  230. VERIFY( m1.try_lock() ); // m1 was not left locked by failed std::lock
  231. m1.unlock();
  232. ++unreliable_lock::throw_on;
  233. }
  234. }
  235. int main()
  236. {
  237. test01();
  238. test02();
  239. test03();
  240. return 0;
  241. }