]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/fiber/test/test_condition_variable_dispatch.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / fiber / test / test_condition_variable_dispatch.cpp
1
2 // Copyright Oliver Kowalke 2013.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // This test is based on the tests of Boost.Thread
8
9 #include <chrono>
10 #include <cstdio>
11 #include <cstdlib>
12 #include <iostream>
13 #include <map>
14 #include <mutex>
15 #include <stdexcept>
16 #include <vector>
17
18 #include <boost/test/unit_test.hpp>
19
20 #include <boost/fiber/all.hpp>
21
22 typedef std::chrono::nanoseconds ns;
23 typedef std::chrono::milliseconds ms;
24
25 int value = 0;
26
27 inline
28 std::chrono::system_clock::time_point delay(int secs, int msecs=0, int nsecs=0) {
29 std::chrono::system_clock::time_point t = std::chrono::system_clock::now();
30 t += std::chrono::seconds( secs);
31 t += std::chrono::milliseconds( msecs);
32 //t += std::chrono::nanoseconds( nsecs);
33
34 return t;
35 }
36
37 struct condition_test_data {
38 condition_test_data() : notified(0), awoken(0) { }
39
40 boost::fibers::mutex mutex;
41 boost::fibers::condition_variable cond;
42 int notified;
43 int awoken;
44 };
45
46 void condition_test_fiber(condition_test_data* data) {
47 std::unique_lock<boost::fibers::mutex> lock(data->mutex);
48 BOOST_CHECK(lock ? true : false);
49 while (!(data->notified > 0))
50 data->cond.wait(lock);
51 BOOST_CHECK(lock ? true : false);
52 data->awoken++;
53 }
54
55 struct cond_predicate {
56 cond_predicate(int& var, int val) : _var(var), _val(val) { }
57
58 bool operator()() { return _var == _val; }
59
60 int& _var;
61 int _val;
62 private:
63 void operator=(cond_predicate&);
64
65 };
66
67 void notify_one_fn( boost::fibers::condition_variable & cond) {
68 cond.notify_one();
69 }
70
71 void notify_all_fn( boost::fibers::condition_variable & cond) {
72 cond.notify_all();
73 }
74
75 void wait_fn(
76 boost::fibers::mutex & mtx,
77 boost::fibers::condition_variable & cond) {
78 std::unique_lock< boost::fibers::mutex > lk( mtx);
79 cond.wait( lk);
80 ++value;
81 }
82
83 void test_one_waiter_notify_one() {
84 value = 0;
85 boost::fibers::mutex mtx;
86 boost::fibers::condition_variable cond;
87
88 boost::fibers::fiber f1(
89 boost::fibers::launch::dispatch,
90 wait_fn,
91 std::ref( mtx),
92 std::ref( cond) );
93 BOOST_CHECK_EQUAL( 0, value);
94
95 boost::fibers::fiber f2(
96 boost::fibers::launch::dispatch,
97 notify_one_fn,
98 std::ref( cond) );
99
100 BOOST_CHECK_EQUAL( 0, value);
101
102 f1.join();
103 f2.join();
104
105 BOOST_CHECK_EQUAL( 1, value);
106 }
107
108 void test_two_waiter_notify_one() {
109 value = 0;
110 boost::fibers::mutex mtx;
111 boost::fibers::condition_variable cond;
112
113 boost::fibers::fiber f1(
114 boost::fibers::launch::dispatch,
115 wait_fn,
116 std::ref( mtx),
117 std::ref( cond) );
118 BOOST_CHECK_EQUAL( 0, value);
119
120 boost::fibers::fiber f2(
121 boost::fibers::launch::dispatch,
122 wait_fn,
123 std::ref( mtx),
124 std::ref( cond) );
125 BOOST_CHECK_EQUAL( 0, value);
126
127 boost::fibers::fiber f3(
128 boost::fibers::launch::dispatch,
129 notify_one_fn,
130 std::ref( cond) );
131 BOOST_CHECK_EQUAL( 0, value);
132
133 boost::fibers::fiber f4(
134 boost::fibers::launch::dispatch,
135 notify_one_fn,
136 std::ref( cond) );
137 BOOST_CHECK_EQUAL( 1, value);
138
139 f1.join();
140 f2.join();
141 f3.join();
142 f4.join();
143
144 BOOST_CHECK_EQUAL( 2, value);
145 }
146
147 void test_two_waiter_notify_all() {
148 value = 0;
149 boost::fibers::mutex mtx;
150 boost::fibers::condition_variable cond;
151
152 boost::fibers::fiber f1(
153 boost::fibers::launch::dispatch,
154 wait_fn,
155 std::ref( mtx),
156 std::ref( cond) );
157 BOOST_CHECK_EQUAL( 0, value);
158
159 boost::fibers::fiber f2(
160 boost::fibers::launch::dispatch,
161 wait_fn,
162 std::ref( mtx),
163 std::ref( cond) );
164 BOOST_CHECK_EQUAL( 0, value);
165
166 boost::fibers::fiber f3(
167 boost::fibers::launch::dispatch,
168 notify_all_fn,
169 std::ref( cond) );
170 BOOST_CHECK_EQUAL( 0, value);
171
172 boost::fibers::fiber f4(
173 boost::fibers::launch::dispatch,
174 wait_fn,
175 std::ref( mtx),
176 std::ref( cond) );
177 BOOST_CHECK_EQUAL( 2, value);
178
179 boost::fibers::fiber f5(
180 boost::fibers::launch::dispatch,
181 notify_all_fn,
182 std::ref( cond) );
183 BOOST_CHECK_EQUAL( 2, value);
184
185 f1.join();
186 f2.join();
187 f3.join();
188 f4.join();
189 f5.join();
190
191 BOOST_CHECK_EQUAL( 3, value);
192 }
193
194 int test1 = 0;
195 int test2 = 0;
196
197 int runs = 0;
198
199 void fn1( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
200 std::unique_lock< boost::fibers::mutex > lk( m);
201 BOOST_CHECK(test2 == 0);
202 test1 = 1;
203 cv.notify_one();
204 while (test2 == 0) {
205 cv.wait(lk);
206 }
207 BOOST_CHECK(test2 != 0);
208 }
209
210 void fn2( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
211 std::unique_lock< boost::fibers::mutex > lk( m);
212 BOOST_CHECK(test2 == 0);
213 test1 = 1;
214 cv.notify_one();
215 std::chrono::system_clock::time_point t0 = std::chrono::system_clock::now();
216 std::chrono::system_clock::time_point t = t0 + ms(250);
217 int count=0;
218 while (test2 == 0 && cv.wait_until(lk, t) == boost::fibers::cv_status::no_timeout)
219 count++;
220 std::chrono::system_clock::time_point t1 = std::chrono::system_clock::now();
221 if (runs == 0) {
222 BOOST_CHECK(t1 - t0 < ms(250));
223 BOOST_CHECK(test2 != 0);
224 } else {
225 BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+5+1000));
226 BOOST_CHECK(test2 == 0);
227 }
228 ++runs;
229 }
230
231 class Pred {
232 int & i_;
233
234 public:
235 explicit Pred(int& i) :
236 i_(i)
237 {}
238
239 bool operator()()
240 { return i_ != 0; }
241 };
242
243 void fn3( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
244 std::unique_lock< boost::fibers::mutex > lk( m);
245 BOOST_CHECK(test2 == 0);
246 test1 = 1;
247 cv.notify_one();
248 std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
249 std::chrono::steady_clock::time_point t = t0 + ms(250);
250 bool r = cv.wait_until(lk, t, Pred(test2));
251 std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
252 if (runs == 0) {
253 BOOST_CHECK(t1 - t0 < ms(250));
254 BOOST_CHECK(test2 != 0);
255 BOOST_CHECK(r);
256 } else {
257 BOOST_CHECK(t1 - t0 - ms(250) < ms(250+2));
258 BOOST_CHECK(test2 == 0);
259 BOOST_CHECK(!r);
260 }
261 ++runs;
262 }
263
264 void fn4( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
265 std::unique_lock< boost::fibers::mutex > lk( m);
266 BOOST_CHECK(test2 == 0);
267 test1 = 1;
268 cv.notify_one();
269 std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
270 int count=0;
271 while (test2 == 0 && cv.wait_for(lk, ms(250)) == boost::fibers::cv_status::no_timeout)
272 count++;
273 std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
274 if (runs == 0) {
275 BOOST_CHECK(t1 - t0 < ms(250));
276 BOOST_CHECK(test2 != 0);
277 } else {
278 BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+5+1000));
279 BOOST_CHECK(test2 == 0);
280 }
281 ++runs;
282 }
283
284 void fn5( boost::fibers::mutex & m, boost::fibers::condition_variable & cv) {
285 std::unique_lock< boost::fibers::mutex > lk( m);
286 BOOST_CHECK(test2 == 0);
287 test1 = 1;
288 cv.notify_one();
289 std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now();
290 int count=0;
291 cv.wait_for(lk, ms(250), Pred(test2));
292 count++;
293 std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
294 if (runs == 0) {
295 BOOST_CHECK(t1 - t0 < ms(250+1000));
296 BOOST_CHECK(test2 != 0);
297 } else {
298 BOOST_CHECK(t1 - t0 - ms(250) < ms(count*250+2));
299 BOOST_CHECK(test2 == 0);
300 }
301 ++runs;
302 }
303
304 void do_test_condition_wait() {
305 test1 = 0;
306 test2 = 0;
307 runs = 0;
308
309 boost::fibers::mutex m;
310 boost::fibers::condition_variable cv;
311 std::unique_lock< boost::fibers::mutex > lk( m);
312 boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn1, std::ref( m), std::ref( cv) );
313 BOOST_CHECK(test1 == 0);
314 while (test1 == 0)
315 cv.wait(lk);
316 BOOST_CHECK(test1 != 0);
317 test2 = 1;
318 lk.unlock();
319 cv.notify_one();
320 f.join();
321 }
322
323 void test_condition_wait() {
324 boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait).join();
325 do_test_condition_wait();
326 }
327
328 void do_test_condition_wait_until() {
329 test1 = 0;
330 test2 = 0;
331 runs = 0;
332
333 boost::fibers::mutex m;
334 boost::fibers::condition_variable cv;
335 {
336 std::unique_lock< boost::fibers::mutex > lk( m);
337 boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn2, std::ref( m), std::ref( cv) );
338 BOOST_CHECK(test1 == 0);
339 while (test1 == 0)
340 cv.wait(lk);
341 BOOST_CHECK(test1 != 0);
342 test2 = 1;
343 lk.unlock();
344 cv.notify_one();
345 f.join();
346 }
347 test1 = 0;
348 test2 = 0;
349 {
350 std::unique_lock< boost::fibers::mutex > lk( m);
351 boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn2, std::ref( m), std::ref( cv) );
352 BOOST_CHECK(test1 == 0);
353 while (test1 == 0)
354 cv.wait(lk);
355 BOOST_CHECK(test1 != 0);
356 lk.unlock();
357 f.join();
358 }
359 }
360
361 void test_condition_wait_until() {
362 boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait_until).join();
363 do_test_condition_wait_until();
364 }
365
366 void do_test_condition_wait_until_pred() {
367 test1 = 0;
368 test2 = 0;
369 runs = 0;
370
371 boost::fibers::mutex m;
372 boost::fibers::condition_variable cv;
373 {
374 std::unique_lock< boost::fibers::mutex > lk( m);
375 boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn3, std::ref( m), std::ref( cv) );
376 BOOST_CHECK(test1 == 0);
377 while (test1 == 0)
378 cv.wait(lk);
379 BOOST_CHECK(test1 != 0);
380 test2 = 1;
381 lk.unlock();
382 cv.notify_one();
383 f.join();
384 }
385 test1 = 0;
386 test2 = 0;
387 {
388 std::unique_lock< boost::fibers::mutex > lk( m);
389 boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn3, std::ref( m), std::ref( cv) );
390 BOOST_CHECK(test1 == 0);
391 while (test1 == 0)
392 cv.wait(lk);
393 BOOST_CHECK(test1 != 0);
394 lk.unlock();
395 f.join();
396 }
397 }
398
399 void test_condition_wait_until_pred() {
400 boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait_until_pred).join();
401 do_test_condition_wait_until_pred();
402 }
403
404 void do_test_condition_wait_for() {
405 test1 = 0;
406 test2 = 0;
407 runs = 0;
408
409 boost::fibers::mutex m;
410 boost::fibers::condition_variable cv;
411 {
412 std::unique_lock< boost::fibers::mutex > lk( m);
413 boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn4, std::ref( m), std::ref( cv) );
414 BOOST_CHECK(test1 == 0);
415 while (test1 == 0)
416 cv.wait(lk);
417 BOOST_CHECK(test1 != 0);
418 test2 = 1;
419 lk.unlock();
420 cv.notify_one();
421 f.join();
422 }
423 test1 = 0;
424 test2 = 0;
425 {
426 std::unique_lock< boost::fibers::mutex > lk( m);
427 boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn4, std::ref( m), std::ref( cv) );
428 BOOST_CHECK(test1 == 0);
429 while (test1 == 0)
430 cv.wait(lk);
431 BOOST_CHECK(test1 != 0);
432 lk.unlock();
433 f.join();
434 }
435 }
436
437 void test_condition_wait_for() {
438 boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait_for).join();
439 do_test_condition_wait_for();
440 }
441
442 void do_test_condition_wait_for_pred() {
443 test1 = 0;
444 test2 = 0;
445 runs = 0;
446
447 boost::fibers::mutex m;
448 boost::fibers::condition_variable cv;
449 {
450 std::unique_lock< boost::fibers::mutex > lk( m);
451 boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn5, std::ref( m), std::ref( cv) );
452 BOOST_CHECK(test1 == 0);
453 while (test1 == 0)
454 cv.wait(lk);
455 BOOST_CHECK(test1 != 0);
456 test2 = 1;
457 lk.unlock();
458 cv.notify_one();
459 f.join();
460 }
461 test1 = 0;
462 test2 = 0;
463 {
464 std::unique_lock< boost::fibers::mutex > lk( m);
465 boost::fibers::fiber f( boost::fibers::launch::dispatch, & fn5, std::ref( m), std::ref( cv) );
466 BOOST_CHECK(test1 == 0);
467 while (test1 == 0)
468 cv.wait(lk);
469 BOOST_CHECK(test1 != 0);
470 lk.unlock();
471 f.join();
472 }
473 }
474
475 void test_condition_wait_for_pred() {
476 boost::fibers::fiber( boost::fibers::launch::dispatch, & do_test_condition_wait_for_pred).join();
477 do_test_condition_wait_for_pred();
478 }
479
480 boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
481 {
482 boost::unit_test::test_suite * test =
483 BOOST_TEST_SUITE("Boost.Fiber: condition_variable test suite");
484
485 test->add( BOOST_TEST_CASE( & test_one_waiter_notify_one) );
486 test->add( BOOST_TEST_CASE( & test_two_waiter_notify_one) );
487 test->add( BOOST_TEST_CASE( & test_two_waiter_notify_all) );
488 test->add( BOOST_TEST_CASE( & test_condition_wait) );
489 test->add( BOOST_TEST_CASE( & test_condition_wait_until) );
490 test->add( BOOST_TEST_CASE( & test_condition_wait_until_pred) );
491 test->add( BOOST_TEST_CASE( & test_condition_wait_for) );
492 test->add( BOOST_TEST_CASE( & test_condition_wait_for_pred) );
493
494 return test;
495 }