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