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 class NonCopyable
157 {
158 #if !defined(__clang__)
159 // GCC 4.8 complains about the following being private
160 public:
NonCopyable(const NonCopyable &)161 NonCopyable(const NonCopyable&)
162 {
163 }
164 #else
165 NonCopyable(const NonCopyable&);
166 #endif
167 public:
NonCopyable()168 NonCopyable() {}
169
operator ()(int &)170 void operator()(int&) {}
171 };
172
173 #if __cplusplus >= 201103L
174 // reference qualifiers on functions are a C++11 extension
175 struct RefQual
176 {
177 int lv_called, rv_called;
178
RefQualRefQual179 RefQual() : lv_called(0), rv_called(0) {}
180
operator ()RefQual181 void operator()() & { ++lv_called; }
operator ()RefQual182 void operator()() && { ++rv_called; }
183 };
184 #endif
185 #endif
186
main()187 int main()
188 {
189 // check basic functionality
190 {
191 std::thread t0(f0);
192 std::thread t1(f0);
193 t0.join();
194 t1.join();
195 assert(init0_called == 1);
196 }
197 // check basic exception safety
198 {
199 std::thread t0(f3);
200 std::thread t1(f3);
201 t0.join();
202 t1.join();
203 assert(init3_called == 2);
204 assert(init3_completed == 1);
205 }
206 // check deadlock avoidance
207 {
208 std::thread t0(f41);
209 std::thread t1(f42);
210 t0.join();
211 t1.join();
212 assert(init41_called == 1);
213 assert(init42_called == 1);
214 }
215 #ifndef _LIBCPP_HAS_NO_VARIADICS
216 // check functors with 1 arg
217 {
218 std::thread t0(f1);
219 std::thread t1(f1);
220 t0.join();
221 t1.join();
222 assert(init1::called == 1);
223 }
224 // check functors with 2 args
225 {
226 std::thread t0(f2);
227 std::thread t1(f2);
228 t0.join();
229 t1.join();
230 assert(init2::called == 5);
231 }
232 {
233 std::once_flag f;
234 std::call_once(f, MoveOnly(), MoveOnly());
235 }
236 // check LWG2442: call_once() shouldn't DECAY_COPY()
237 {
238 std::once_flag f;
239 int i = 0;
240 std::call_once(f, NonCopyable(), i);
241 }
242 #if __cplusplus >= 201103L
243 // reference qualifiers on functions are a C++11 extension
244 {
245 std::once_flag f1, f2;
246 RefQual rq;
247 std::call_once(f1, rq);
248 assert(rq.lv_called == 1);
249 std::call_once(f2, std::move(rq));
250 assert(rq.rv_called == 1);
251 }
252 #endif
253 #endif // _LIBCPP_HAS_NO_VARIADICS
254 }
255