1 //===----------------------------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // UNSUPPORTED: libcpp-has-no-threads
11
12 // <mutex>
13
14 // struct once_flag;
15
16 // template<class Callable, class ...Args>
17 // void call_once(once_flag& flag, Callable func, Args&&... args);
18
19 #include <mutex>
20 #include <thread>
21 #include <cassert>
22
23 typedef std::chrono::milliseconds ms;
24
25 std::once_flag flg0;
26
27 int init0_called = 0;
28
init0()29 void init0()
30 {
31 std::this_thread::sleep_for(ms(250));
32 ++init0_called;
33 }
34
f0()35 void f0()
36 {
37 std::call_once(flg0, init0);
38 }
39
40 std::once_flag flg3;
41
42 int init3_called = 0;
43 int init3_completed = 0;
44
init3()45 void init3()
46 {
47 ++init3_called;
48 std::this_thread::sleep_for(ms(250));
49 if (init3_called == 1)
50 throw 1;
51 ++init3_completed;
52 }
53
f3()54 void f3()
55 {
56 try
57 {
58 std::call_once(flg3, init3);
59 }
60 catch (...)
61 {
62 }
63 }
64
65 #ifndef _LIBCPP_HAS_NO_VARIADICS
66
67 struct init1
68 {
69 static int called;
70
operator ()init171 void operator()(int i) {called += i;}
72 };
73
74 int init1::called = 0;
75
76 std::once_flag flg1;
77
f1()78 void f1()
79 {
80 std::call_once(flg1, init1(), 1);
81 }
82
83 struct init2
84 {
85 static int called;
86
operator ()init287 void operator()(int i, int j) const {called += i + j;}
88 };
89
90 int init2::called = 0;
91
92 std::once_flag flg2;
93
f2()94 void f2()
95 {
96 std::call_once(flg2, init2(), 2, 3);
97 std::call_once(flg2, init2(), 4, 5);
98 }
99
100 #endif // _LIBCPP_HAS_NO_VARIADICS
101
102 std::once_flag flg41;
103 std::once_flag flg42;
104
105 int init41_called = 0;
106 int init42_called = 0;
107
108 void init42();
109
init41()110 void init41()
111 {
112 std::this_thread::sleep_for(ms(250));
113 ++init41_called;
114 }
115
init42()116 void init42()
117 {
118 std::this_thread::sleep_for(ms(250));
119 ++init42_called;
120 }
121
f41()122 void f41()
123 {
124 std::call_once(flg41, init41);
125 std::call_once(flg42, init42);
126 }
127
f42()128 void f42()
129 {
130 std::call_once(flg42, init42);
131 std::call_once(flg41, init41);
132 }
133
134 #ifndef _LIBCPP_HAS_NO_VARIADICS
135
136 class MoveOnly
137 {
138 #if !defined(__clang__)
139 // GCC 4.8 complains about the following being private
140 public:
MoveOnly(const MoveOnly &)141 MoveOnly(const MoveOnly&)
142 {
143 }
144 #else
145 MoveOnly(const MoveOnly&);
146 #endif
147 public:
MoveOnly()148 MoveOnly() {}
MoveOnly(MoveOnly &&)149 MoveOnly(MoveOnly&&) {}
150
operator ()(MoveOnly &&)151 void operator()(MoveOnly&&)
152 {
153 }
154 };
155
156 #endif
157
main()158 int main()
159 {
160 // check basic functionality
161 {
162 std::thread t0(f0);
163 std::thread t1(f0);
164 t0.join();
165 t1.join();
166 assert(init0_called == 1);
167 }
168 // check basic exception safety
169 {
170 std::thread t0(f3);
171 std::thread t1(f3);
172 t0.join();
173 t1.join();
174 assert(init3_called == 2);
175 assert(init3_completed == 1);
176 }
177 // check deadlock avoidance
178 {
179 std::thread t0(f41);
180 std::thread t1(f42);
181 t0.join();
182 t1.join();
183 assert(init41_called == 1);
184 assert(init42_called == 1);
185 }
186 #ifndef _LIBCPP_HAS_NO_VARIADICS
187 // check functors with 1 arg
188 {
189 std::thread t0(f1);
190 std::thread t1(f1);
191 t0.join();
192 t1.join();
193 assert(init1::called == 1);
194 }
195 // check functors with 2 args
196 {
197 std::thread t0(f2);
198 std::thread t1(f2);
199 t0.join();
200 t1.join();
201 assert(init2::called == 5);
202 }
203 {
204 std::once_flag f;
205 std::call_once(f, MoveOnly(), MoveOnly());
206 }
207 #endif // _LIBCPP_HAS_NO_VARIADICS
208 }
209