]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/30_threads/lock/4.cc
a12d6276284dfe4ac41dfd03a4c38d3dfa7fbc77
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 30_threads / lock / 4.cc
1 // { dg-do run { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-rtems* *-*-darwin* powerpc-ibm-aix* } }
2 // { dg-options "-pthread" { target *-*-freebsd* *-*-dragonfly* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* powerpc-ibm-aix* } }
3 // { dg-require-effective-target c++11 }
4 // { dg-require-cstdint "" }
5 // { dg-require-gthreads "" }
6
7 // Copyright (C) 2010-2016 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 bool test __attribute__((unused)) = true;
42 VERIFY( !l.owns_lock() );
43 }
44
45 void lock()
46 {
47 if (count == throw_on)
48 throw throw_on;
49 ++count;
50 l.lock();
51 }
52 bool try_lock()
53 {
54 if (count == throw_on)
55 throw throw_on;
56 std::unique_lock<std::mutex> l2(m, std::defer_lock);
57 if (count == lock_on)
58 l2.lock();
59 ++count;
60 return l.try_lock();
61 }
62
63 void unlock()
64 {
65 bool test __attribute__((unused)) = true;
66 VERIFY( l.owns_lock() );
67 l.unlock();
68 }
69
70 };
71
72 int unreliable_lock::count = 0;
73 int unreliable_lock::throw_on = -1;
74 int unreliable_lock::lock_on = -1;
75
76 void test01()
77 {
78 bool test __attribute__((unused)) = true;
79
80 unreliable_lock l1, l2, l3;
81
82 try
83 {
84 unreliable_lock::count = 0;
85 std::lock(l1, l2, l3);
86 VERIFY( unreliable_lock::count == 3 );
87 l1.unlock();
88 l2.unlock();
89 l3.unlock();
90 }
91 catch (...)
92 {
93 VERIFY( false );
94 }
95 }
96
97 void test02()
98 {
99 bool test __attribute__((unused)) = true;
100
101 // test behaviour when a lock is already held
102 try
103 {
104 unreliable_lock::lock_on = 1;
105 while (unreliable_lock::lock_on < 3)
106 {
107 unreliable_lock::count = 0;
108 unreliable_lock l1, l2, l3;
109 std::lock(l1, l2, l3);
110 VERIFY( unreliable_lock::count > 3 );
111 l1.unlock();
112 l2.unlock();
113 l3.unlock();
114 ++unreliable_lock::lock_on;
115 }
116 }
117 catch (...)
118 {
119 VERIFY( false );
120 }
121 }
122
123 void test03()
124 {
125 // test behaviour when an exception is thrown
126 unreliable_lock::throw_on = 0;
127 while (unreliable_lock::throw_on < 3)
128 {
129 unreliable_lock::count = 0;
130 unreliable_lock l1, l2, l3;
131 bool test = false;
132 try
133 {
134 std::lock(l1, l2, l3);
135 }
136 catch (...)
137 {
138 test = true;
139 }
140 VERIFY( test );
141 ++unreliable_lock::throw_on;
142 }
143 }
144
145 int main()
146 {
147 test01();
148 test02();
149 test03();
150 return 0;
151 }