]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/30_threads/lock/4.cc
01b3c1776a30f8ab636ff13d7be831592babb677
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 30_threads / lock / 4.cc
1 // { dg-do run }
2 // { dg-options "-pthread" }
3 // { dg-require-effective-target c++11 }
4 // { dg-require-effective-target pthread }
5 // { dg-require-gthreads "" }
6
7 // Copyright (C) 2010-2020 Free Software Foundation, Inc.
8 //
9 // This file is part of the GNU ISO C++ Library. This library is free
10 // software; you can redistribute it and/or modify it under the
11 // terms of the GNU General Public License as published by the
12 // Free Software Foundation; either version 3, or (at your option)
13 // any later version.
14
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19
20 // You should have received a copy of the GNU General Public License along
21 // with this library; see the file COPYING3. If not see
22 // <http://www.gnu.org/licenses/>.
23
24
25 #include <mutex>
26 #include <testsuite_hooks.h>
27
28 struct unreliable_lock
29 {
30 std::mutex m;
31 std::unique_lock<std::mutex> l;
32
33 static int count;
34 static int throw_on;
35 static int lock_on;
36
37 unreliable_lock() : l(m, std::defer_lock) { }
38
39 ~unreliable_lock()
40 {
41 VERIFY( !l.owns_lock() );
42 }
43
44 void lock()
45 {
46 if (count == throw_on)
47 throw throw_on;
48 ++count;
49 l.lock();
50 }
51 bool try_lock()
52 {
53 if (count == throw_on)
54 throw throw_on;
55 std::unique_lock<std::mutex> l2(m, std::defer_lock);
56 if (count == lock_on)
57 l2.lock();
58 ++count;
59 return l.try_lock();
60 }
61
62 void unlock()
63 {
64 VERIFY( l.owns_lock() );
65 l.unlock();
66 }
67
68 };
69
70 int unreliable_lock::count = 0;
71 int unreliable_lock::throw_on = -1;
72 int unreliable_lock::lock_on = -1;
73
74 void test01()
75 {
76 unreliable_lock l1, l2, l3;
77
78 try
79 {
80 unreliable_lock::count = 0;
81 std::lock(l1, l2, l3);
82 VERIFY( unreliable_lock::count == 3 );
83 l1.unlock();
84 l2.unlock();
85 l3.unlock();
86 }
87 catch (...)
88 {
89 VERIFY( false );
90 }
91 }
92
93 void test02()
94 {
95 // test behaviour when a lock is already held
96 try
97 {
98 unreliable_lock::lock_on = 1;
99 while (unreliable_lock::lock_on < 3)
100 {
101 unreliable_lock::count = 0;
102 unreliable_lock l1, l2, l3;
103 std::lock(l1, l2, l3);
104 VERIFY( unreliable_lock::count > 3 );
105 l1.unlock();
106 l2.unlock();
107 l3.unlock();
108 ++unreliable_lock::lock_on;
109 }
110 }
111 catch (...)
112 {
113 VERIFY( false );
114 }
115 }
116
117 void test03()
118 {
119 // test behaviour when an exception is thrown
120 unreliable_lock::throw_on = 0;
121 while (unreliable_lock::throw_on < 3)
122 {
123 unreliable_lock::count = 0;
124 unreliable_lock l1, l2, l3;
125 bool test = false;
126 try
127 {
128 std::lock(l1, l2, l3);
129 }
130 catch (...)
131 {
132 test = true;
133 }
134 VERIFY( test );
135 ++unreliable_lock::throw_on;
136 }
137 }
138
139 int main()
140 {
141 test01();
142 test02();
143 test03();
144 return 0;
145 }