]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/thread/test/sync/mutual_exclusion/once/call_once/call_once_pass.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / thread / test / sync / mutual_exclusion / once / call_once / call_once_pass.cpp
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 // Copyright (C) 2013 Vicente J. Botet Escriba
11 //
12 // Distributed under the Boost Software License, Version 1.0. (See accompanying
13 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
14
15 // <boost/thread/once.hpp>
16
17 // struct once_flag;
18
19 // template<class Callable, class ...Args>
20 // void call_once(once_flag& flag, Callable&& func, Args&&... args);
21
22 //#define BOOST_THREAD_VERSION 4
23 #define BOOST_THREAD_USES_MOVE
24 #define BOOST_THREAD_PROVIDES_ONCE_CXX11
25
26 #include <boost/thread/once.hpp>
27 #include <boost/thread/thread.hpp>
28 #include <boost/detail/lightweight_test.hpp>
29
30 #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
31 #define BOOST_INIT_ONCE_INIT
32 #else
33 #define BOOST_INIT_ONCE_INIT =BOOST_ONCE_INIT
34 #endif
35
36 typedef boost::chrono::milliseconds ms;
37
38 boost::once_flag flg0 BOOST_INIT_ONCE_INIT;
39
40 int init0_called = 0;
41
42 void init0()
43 {
44 boost::this_thread::sleep_for(ms(250));
45 ++init0_called;
46 }
47
48 void f0()
49 {
50 boost::call_once(flg0, init0);
51 }
52
53 boost::once_flag flg3 BOOST_INIT_ONCE_INIT;
54
55 int init3_called = 0;
56 int init3_completed = 0;
57
58 void init3()
59 {
60 ++init3_called;
61 boost::this_thread::sleep_for(ms(250));
62 if (init3_called == 1)
63 throw 1;
64 ++init3_completed;
65 }
66
67 void f3()
68 {
69 try
70 {
71 boost::call_once(flg3, init3);
72 }
73 catch (...)
74 {
75 }
76 }
77
78 struct init1
79 {
80 static int called;
81 typedef void result_type;
82
83 void operator()(int i) {called += i;}
84 void operator()(int i) const {called += i;}
85 };
86
87 int init1::called = 0;
88
89 boost::once_flag flg1 BOOST_INIT_ONCE_INIT;
90
91 void f1()
92 {
93 boost::call_once(flg1, init1(), 1);
94 }
95
96 boost::once_flag flg1_member BOOST_INIT_ONCE_INIT;
97
98 struct init1_member
99 {
100 static int called;
101 typedef void result_type;
102 void call(int i) {
103 called += i;
104 }
105 };
106 int init1_member::called = 0;
107
108 void f1_member_l()
109 {
110 init1_member o;
111 int i=1;
112 boost::call_once(flg1_member, &init1_member::call, o, i);
113 }
114 void f1_member_r()
115 {
116 init1_member o;
117 boost::call_once(flg1_member, &init1_member::call, o, 1);
118 }
119 struct init2
120 {
121 static int called;
122 typedef void result_type;
123
124 void operator()(int i, int j) {called += i + j;}
125 void operator()(int i, int j) const {called += i + j;}
126 };
127
128 int init2::called = 0;
129
130 boost::once_flag flg2 BOOST_INIT_ONCE_INIT;
131
132 void f2()
133 {
134 boost::call_once(flg2, init2(), 2, 3);
135 boost::call_once(flg2, init2(), 4, 5);
136 }
137
138 boost::once_flag flg41 BOOST_INIT_ONCE_INIT;
139 boost::once_flag flg42 BOOST_INIT_ONCE_INIT;
140
141 int init41_called = 0;
142 int init42_called = 0;
143
144 void init42();
145
146 void init41()
147 {
148 boost::this_thread::sleep_for(ms(250));
149 ++init41_called;
150 }
151
152 void init42()
153 {
154 boost::this_thread::sleep_for(ms(250));
155 ++init42_called;
156 }
157
158 void f41()
159 {
160 boost::call_once(flg41, init41);
161 boost::call_once(flg42, init42);
162 }
163
164 void f42()
165 {
166 boost::call_once(flg42, init42);
167 boost::call_once(flg41, init41);
168 }
169
170 class MoveOnly
171 {
172 public:
173 typedef void result_type;
174
175 BOOST_THREAD_MOVABLE_ONLY(MoveOnly)
176 MoveOnly()
177 {
178 }
179 MoveOnly(BOOST_THREAD_RV_REF(MoveOnly))
180 {}
181
182 void operator()(BOOST_THREAD_RV_REF(MoveOnly))
183 {
184 }
185 void operator()(int)
186 {
187 }
188 void operator()()
189 {
190 }
191 };
192
193
194 struct id_string
195 {
196 static boost::once_flag flag;
197 static void do_init(id_string & )
198 {}
199 void operator()()
200 {
201 boost::call_once(flag, &id_string::do_init, boost::ref(*this));
202 }
203 // void operator()(int,int)
204 // {
205 // // This should fail but works with gcc-4.6.3
206 // //std::bind(&id_string::do_init, *this)();
207 // std::bind(&id_string::do_init, std::ref(*this))();
208 // }
209 // void operator()(int) const
210 // {
211 // //std::bind(&id_string::do_init, *this)();
212 // }
213 };
214
215
216 boost::once_flag id_string::flag BOOST_INIT_ONCE_INIT;
217
218 int main()
219 {
220
221 //
222 {
223 id_string id;
224 id();
225 //id(1,1);
226 }
227 // check basic functionality
228 {
229 boost::thread t0(f0);
230 boost::thread t1(f0);
231 t0.join();
232 t1.join();
233 BOOST_TEST(init0_called == 1);
234 }
235 // check basic exception safety
236 {
237 boost::thread t0(f3);
238 boost::thread t1(f3);
239 t0.join();
240 t1.join();
241 BOOST_TEST(init3_called == 2);
242 BOOST_TEST(init3_completed == 1);
243 }
244 // check deadlock avoidance
245 {
246 boost::thread t0(f41);
247 boost::thread t1(f42);
248 t0.join();
249 t1.join();
250 BOOST_TEST(init41_called == 1);
251 BOOST_TEST(init42_called == 1);
252 }
253 // check functors with 1 arg
254 {
255 boost::thread t0(f1);
256 boost::thread t1(f1);
257 t0.join();
258 t1.join();
259 BOOST_TEST(init1::called == 1);
260 }
261 // check functors with 2 args
262 {
263 boost::thread t0(f2);
264 boost::thread t1(f2);
265 t0.join();
266 t1.join();
267 BOOST_TEST(init2::called == 5);
268 }
269
270 // check member function with 1 arg
271 {
272 boost::thread t0(f1_member_l);
273 boost::thread t1(f1_member_r);
274 t0.join();
275 t1.join();
276 BOOST_TEST(init1_member::called == 1);
277 }
278 #if defined BOOST_THREAD_PLATFORM_PTHREAD || (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__ > 40600)
279 {
280 boost::once_flag f BOOST_INIT_ONCE_INIT;
281 boost::call_once(f, MoveOnly());
282 }
283 #endif
284 #if defined BOOST_THREAD_PROVIDES_INVOKE
285 {
286 boost::once_flag f BOOST_INIT_ONCE_INIT;
287 boost::call_once(f, MoveOnly(), 1);
288 }
289 {
290 boost::once_flag f BOOST_INIT_ONCE_INIT;
291 boost::call_once(f, MoveOnly(), MoveOnly());
292 }
293 #endif // BOOST_THREAD_PLATFORM_PTHREAD
294 return boost::report_errors();
295 }
296
297