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 MoveOnly(const MoveOnly&);
137 public:
MoveOnly()138 MoveOnly() {}
MoveOnly(MoveOnly &&)139 MoveOnly(MoveOnly&&) {}
140
operator ()(MoveOnly &&)141 void operator()(MoveOnly&&)
142 {
143 }
144 };
145
146 #endif
147
main()148 int main()
149 {
150 // check basic functionality
151 {
152 std::thread t0(f0);
153 std::thread t1(f0);
154 t0.join();
155 t1.join();
156 assert(init0_called == 1);
157 }
158 // check basic exception safety
159 {
160 std::thread t0(f3);
161 std::thread t1(f3);
162 t0.join();
163 t1.join();
164 assert(init3_called == 2);
165 assert(init3_completed == 1);
166 }
167 // check deadlock avoidance
168 {
169 std::thread t0(f41);
170 std::thread t1(f42);
171 t0.join();
172 t1.join();
173 assert(init41_called == 1);
174 assert(init42_called == 1);
175 }
176 #ifndef _LIBCPP_HAS_NO_VARIADICS
177 // check functors with 1 arg
178 {
179 std::thread t0(f1);
180 std::thread t1(f1);
181 t0.join();
182 t1.join();
183 assert(init1::called == 1);
184 }
185 // check functors with 2 args
186 {
187 std::thread t0(f2);
188 std::thread t1(f2);
189 t0.join();
190 t1.join();
191 assert(init2::called == 5);
192 }
193 {
194 std::once_flag f;
195 std::call_once(f, MoveOnly(), MoveOnly());
196 }
197 #endif // _LIBCPP_HAS_NO_VARIADICS
198 }
199