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