]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/fiber/test/test_shared_future_dispatch.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / fiber / test / test_shared_future_dispatch.cpp
1 // (C) Copyright 2008-10 Anthony Williams
2 // 2015 Oliver Kowalke
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7
8 #include <chrono>
9 #include <memory>
10 #include <stdexcept>
11 #include <string>
12 #include <utility>
13
14 #include <boost/test/unit_test.hpp>
15
16 #include <boost/fiber/all.hpp>
17
18 typedef std::chrono::milliseconds ms;
19 typedef std::chrono::high_resolution_clock Clock;
20
21 int gi = 7;
22
23 struct my_exception : public std::runtime_error {
24 my_exception() :
25 std::runtime_error("my_exception") {
26 }
27 };
28
29 struct A {
30 A() = default;
31
32 A( A const&) = delete;
33 A( A &&) = default;
34
35 A & operator=( A const&) = delete;
36 A & operator=( A &&) = default;
37
38 int value;
39 };
40
41 void fn1( boost::fibers::promise< int > * p, int i) {
42 boost::this_fiber::yield();
43 p->set_value( i);
44 }
45
46 void fn2() {
47 boost::fibers::promise< int > p;
48 boost::fibers::shared_future< int > f( p.get_future().share() );
49 boost::this_fiber::yield();
50 boost::fibers::fiber( boost::fibers::launch::dispatch, fn1, & p, 7).detach();
51 boost::this_fiber::yield();
52 BOOST_CHECK( 7 == f.get() );
53 }
54
55 int fn3() {
56 return 3;
57 }
58
59 void fn4() {
60 }
61
62 int fn5() {
63 boost::throw_exception( my_exception() );
64 return 3;
65 }
66
67 void fn6() {
68 boost::throw_exception( my_exception() );
69 }
70
71 int & fn7() {
72 return gi;
73 }
74
75 int fn8( int i) {
76 return i;
77 }
78
79 A fn9() {
80 A a;
81 a.value = 3;
82 return std::move( a);
83 }
84
85 A fn10() {
86 boost::throw_exception( my_exception() );
87 return A();
88 }
89
90 void fn11( boost::fibers::promise< int > p) {
91 boost::this_fiber::sleep_for( ms(500) );
92 p.set_value(3);
93 }
94
95 void fn12( boost::fibers::promise< int& > p) {
96 boost::this_fiber::sleep_for( ms(500) );
97 gi = 5;
98 p.set_value( gi);
99 }
100
101 void fn13( boost::fibers::promise< void > p) {
102 boost::this_fiber::sleep_for( ms(500) );
103 p.set_value();
104 }
105
106 // shared_future
107 void test_shared_future_create() {
108 {
109 // default constructed and assigned shared_future is not valid
110 boost::fibers::shared_future< int > f1;
111 boost::fibers::shared_future< int > f2 = f1;
112 BOOST_CHECK( ! f1.valid() );
113 BOOST_CHECK( ! f2.valid() );
114 }
115
116 {
117 // shared_future retrieved from promise is valid
118 boost::fibers::promise< int > p;
119 boost::fibers::shared_future< int > f1 = p.get_future();
120 boost::fibers::shared_future< int > f2 = f1;
121 BOOST_CHECK( f1.valid() );
122 BOOST_CHECK( f2.valid() );
123 }
124 }
125
126 void test_shared_future_create_ref() {
127 {
128 // default constructed and assigned shared_future is not valid
129 boost::fibers::shared_future< int& > f1;
130 boost::fibers::shared_future< int& > f2 = f1;
131 BOOST_CHECK( ! f1.valid() );
132 BOOST_CHECK( ! f2.valid() );
133 }
134
135 {
136 // shared_future retrieved from promise is valid
137 boost::fibers::promise< int& > p;
138 boost::fibers::shared_future< int& > f1 = p.get_future();
139 boost::fibers::shared_future< int& > f2 = f1;
140 BOOST_CHECK( f1.valid() );
141 BOOST_CHECK( f2.valid() );
142 }
143 }
144
145 void test_shared_future_create_void() {
146 {
147 // default constructed and assigned shared_future is not valid
148 boost::fibers::shared_future< void > f1;
149 boost::fibers::shared_future< void > f2 = f1;
150 BOOST_CHECK( ! f1.valid() );
151 BOOST_CHECK( ! f2.valid() );
152 }
153
154 {
155 // shared_future retrieved from promise is valid
156 boost::fibers::promise< void > p;
157 boost::fibers::shared_future< void > f1 = p.get_future();
158 boost::fibers::shared_future< void > f2 = f1;
159 BOOST_CHECK( f1.valid() );
160 BOOST_CHECK( f2.valid() );
161 }
162 }
163
164 void test_shared_future_get() {
165 // future retrieved from promise is valid (if it is the first)
166 boost::fibers::promise< int > p1;
167 p1.set_value( 7);
168
169 boost::fibers::shared_future< int > f1 = p1.get_future().share();
170 BOOST_CHECK( f1.valid() );
171
172 // get
173 BOOST_CHECK( ! f1.get_exception_ptr() );
174 BOOST_CHECK( 7 == f1.get() );
175 BOOST_CHECK( f1.valid() );
176
177 // throw broken_promise if promise is destroyed without set
178 {
179 boost::fibers::promise< int > p2;
180 f1 = p2.get_future().share();
181 }
182 bool thrown = false;
183 try {
184 f1.get();
185 } catch ( boost::fibers::broken_promise const&) {
186 thrown = true;
187 }
188 BOOST_CHECK( f1.valid() );
189 BOOST_CHECK( thrown);
190 }
191
192 void test_shared_future_get_move() {
193 // future retrieved from promise is valid (if it is the first)
194 boost::fibers::promise< A > p1;
195 A a; a.value = 7;
196 p1.set_value( std::move( a) );
197
198 boost::fibers::shared_future< A > f1 = p1.get_future().share();
199 BOOST_CHECK( f1.valid() );
200
201 // get
202 BOOST_CHECK( ! f1.get_exception_ptr() );
203 BOOST_CHECK( 7 == f1.get().value);
204 BOOST_CHECK( f1.valid() );
205
206 // throw broken_promise if promise is destroyed without set
207 {
208 boost::fibers::promise< A > p2;
209 f1 = p2.get_future().share();
210 }
211 bool thrown = false;
212 try {
213 f1.get();
214 } catch ( boost::fibers::broken_promise const&) {
215 thrown = true;
216 }
217 BOOST_CHECK( f1.valid() );
218 BOOST_CHECK( thrown);
219 }
220
221 void test_shared_future_get_ref() {
222 // future retrieved from promise is valid (if it is the first)
223 boost::fibers::promise< int& > p1;
224 int i = 7;
225 p1.set_value( i);
226
227 boost::fibers::shared_future< int& > f1 = p1.get_future().share();
228 BOOST_CHECK( f1.valid() );
229
230 // get
231 BOOST_CHECK( ! f1.get_exception_ptr() );
232 int & j = f1.get();
233 BOOST_CHECK( &i == &j);
234 BOOST_CHECK( f1.valid() );
235
236 // throw broken_promise if promise is destroyed without set
237 {
238 boost::fibers::promise< int& > p2;
239 f1 = p2.get_future().share();
240 }
241 bool thrown = false;
242 try {
243 f1.get();
244 } catch ( boost::fibers::broken_promise const&) {
245 thrown = true;
246 }
247 BOOST_CHECK( f1.valid() );
248 BOOST_CHECK( thrown);
249 }
250
251
252 void test_shared_future_get_void() {
253 // future retrieved from promise is valid (if it is the first)
254 boost::fibers::promise< void > p1;
255 p1.set_value();
256
257 boost::fibers::shared_future< void > f1 = p1.get_future().share();
258 BOOST_CHECK( f1.valid() );
259
260 // get
261 BOOST_CHECK( ! f1.get_exception_ptr() );
262 f1.get();
263 BOOST_CHECK( f1.valid() );
264
265 // throw broken_promise if promise is destroyed without set
266 {
267 boost::fibers::promise< void > p2;
268 f1 = p2.get_future().share();
269 }
270 bool thrown = false;
271 try {
272 f1.get();
273 } catch ( boost::fibers::broken_promise const&) {
274 thrown = true;
275 }
276 BOOST_CHECK( f1.valid() );
277 BOOST_CHECK( thrown);
278 }
279
280 void test_future_share() {
281 // future retrieved from promise is valid (if it is the first)
282 boost::fibers::promise< int > p1;
283 int i = 7;
284 p1.set_value( i);
285
286 boost::fibers::future< int > f1 = p1.get_future();
287 BOOST_CHECK( f1.valid() );
288
289 // share
290 boost::fibers::shared_future< int > sf1 = f1.share();
291 BOOST_CHECK( sf1.valid() );
292 BOOST_CHECK( ! f1.valid() );
293
294 // get
295 BOOST_CHECK( ! sf1.get_exception_ptr() );
296 int j = sf1.get();
297 BOOST_CHECK_EQUAL( i, j);
298 BOOST_CHECK( sf1.valid() );
299 }
300
301 void test_future_share_ref() {
302 // future retrieved from promise is valid (if it is the first)
303 boost::fibers::promise< int& > p1;
304 int i = 7;
305 p1.set_value( i);
306
307 boost::fibers::future< int& > f1 = p1.get_future();
308 BOOST_CHECK( f1.valid() );
309
310 // share
311 boost::fibers::shared_future< int& > sf1 = f1.share();
312 BOOST_CHECK( sf1.valid() );
313 BOOST_CHECK( ! f1.valid() );
314
315 // get
316 BOOST_CHECK( ! sf1.get_exception_ptr() );
317 int & j = sf1.get();
318 BOOST_CHECK( &i == &j);
319 BOOST_CHECK( sf1.valid() );
320 }
321
322 void test_future_share_void() {
323 // future retrieved from promise is valid (if it is the first)
324 boost::fibers::promise< void > p1;
325 p1.set_value();
326
327 boost::fibers::future< void > f1 = p1.get_future();
328 BOOST_CHECK( f1.valid() );
329
330 // share
331 boost::fibers::shared_future< void > sf1 = f1.share();
332 BOOST_CHECK( sf1.valid() );
333 BOOST_CHECK( ! f1.valid() );
334
335 // get
336 BOOST_CHECK( ! sf1.get_exception_ptr() );
337 sf1.get();
338 BOOST_CHECK( sf1.valid() );
339 }
340
341 void test_shared_future_wait() {
342 // future retrieved from promise is valid (if it is the first)
343 boost::fibers::promise< int > p1;
344 boost::fibers::shared_future< int > f1 = p1.get_future().share();
345
346 // wait on future
347 p1.set_value( 7);
348 f1.wait();
349 BOOST_CHECK( 7 == f1.get() );
350 }
351
352 void test_shared_future_wait_ref() {
353 // future retrieved from promise is valid (if it is the first)
354 boost::fibers::promise< int& > p1;
355 boost::fibers::shared_future< int& > f1 = p1.get_future().share();
356
357 // wait on future
358 int i = 7;
359 p1.set_value( i);
360 f1.wait();
361 int & j = f1.get();
362 BOOST_CHECK( &i == &j);
363 }
364
365 void test_shared_future_wait_void() {
366 // future retrieved from promise is valid (if it is the first)
367 boost::fibers::promise< void > p1;
368 boost::fibers::shared_future< void > f1 = p1.get_future().share();
369
370 // wait on future
371 p1.set_value();
372 f1.wait();
373 f1.get();
374 BOOST_CHECK( f1.valid() );
375 }
376
377 void test_shared_future_wait_for() {
378 // future retrieved from promise is valid (if it is the first)
379 boost::fibers::promise< int > p1;
380 boost::fibers::shared_future< int > f1 = p1.get_future().share();
381
382 boost::fibers::fiber( boost::fibers::launch::dispatch, fn11, std::move( p1) ).detach();
383
384 // wait on future
385 BOOST_CHECK( f1.valid() );
386 boost::fibers::future_status status = f1.wait_for( ms(300) );
387 BOOST_CHECK( boost::fibers::future_status::timeout == status);
388
389 BOOST_CHECK( f1.valid() );
390 status = f1.wait_for( ms(300) );
391 BOOST_CHECK( boost::fibers::future_status::ready == status);
392
393 BOOST_CHECK( f1.valid() );
394 f1.wait();
395 }
396
397 void test_shared_future_wait_for_ref() {
398 // future retrieved from promise is valid (if it is the first)
399 boost::fibers::promise< int& > p1;
400 boost::fibers::shared_future< int& > f1 = p1.get_future().share();
401
402 boost::fibers::fiber( boost::fibers::launch::dispatch, fn12, std::move( p1) ).detach();
403
404 // wait on future
405 BOOST_CHECK( f1.valid() );
406 boost::fibers::future_status status = f1.wait_for( ms(300) );
407 BOOST_CHECK( boost::fibers::future_status::timeout == status);
408
409 BOOST_CHECK( f1.valid() );
410 status = f1.wait_for( ms(300) );
411 BOOST_CHECK( boost::fibers::future_status::ready == status);
412
413 BOOST_CHECK( f1.valid() );
414 f1.wait();
415 }
416
417 void test_shared_future_wait_for_void() {
418 // future retrieved from promise is valid (if it is the first)
419 boost::fibers::promise< void > p1;
420 boost::fibers::shared_future< void > f1 = p1.get_future().share();
421
422 boost::fibers::fiber( boost::fibers::launch::dispatch, fn13, std::move( p1) ).detach();
423
424 // wait on future
425 BOOST_CHECK( f1.valid() );
426 boost::fibers::future_status status = f1.wait_for( ms(300) );
427 BOOST_CHECK( boost::fibers::future_status::timeout == status);
428
429 BOOST_CHECK( f1.valid() );
430 status = f1.wait_for( ms(300) );
431 BOOST_CHECK( boost::fibers::future_status::ready == status);
432
433 BOOST_CHECK( f1.valid() );
434 f1.wait();
435 }
436
437 void test_shared_future_wait_until() {
438 // future retrieved from promise is valid (if it is the first)
439 boost::fibers::promise< int > p1;
440 boost::fibers::shared_future< int > f1 = p1.get_future().share();
441
442 boost::fibers::fiber( boost::fibers::launch::dispatch, fn11, std::move( p1) ).detach();
443
444 // wait on future
445 BOOST_CHECK( f1.valid() );
446 boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
447 BOOST_CHECK( boost::fibers::future_status::timeout == status);
448
449 BOOST_CHECK( f1.valid() );
450 status = f1.wait_until( Clock::now() + ms(300) );
451 BOOST_CHECK( boost::fibers::future_status::ready == status);
452
453 BOOST_CHECK( f1.valid() );
454 f1.wait();
455 }
456
457 void test_shared_future_wait_until_ref() {
458 // future retrieved from promise is valid (if it is the first)
459 boost::fibers::promise< int& > p1;
460 boost::fibers::shared_future< int& > f1 = p1.get_future().share();
461
462 boost::fibers::fiber( boost::fibers::launch::dispatch, fn12, std::move( p1) ).detach();
463
464 // wait on future
465 BOOST_CHECK( f1.valid() );
466 boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
467 BOOST_CHECK( boost::fibers::future_status::timeout == status);
468
469 BOOST_CHECK( f1.valid() );
470 status = f1.wait_until( Clock::now() + ms(300) );
471 BOOST_CHECK( boost::fibers::future_status::ready == status);
472
473 BOOST_CHECK( f1.valid() );
474 f1.wait();
475 }
476
477 void test_shared_future_wait_until_void() {
478 // future retrieved from promise is valid (if it is the first)
479 boost::fibers::promise< void > p1;
480 boost::fibers::shared_future< void > f1 = p1.get_future().share();
481
482 boost::fibers::fiber( boost::fibers::launch::dispatch, fn13, std::move( p1) ).detach();
483
484 // wait on future
485 BOOST_CHECK( f1.valid() );
486 boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
487 BOOST_CHECK( boost::fibers::future_status::timeout == status);
488
489 BOOST_CHECK( f1.valid() );
490 status = f1.wait_until( Clock::now() + ms(300) );
491 BOOST_CHECK( boost::fibers::future_status::ready == status);
492
493 BOOST_CHECK( f1.valid() );
494 f1.wait();
495 }
496
497 void test_shared_future_wait_with_fiber_1() {
498 boost::fibers::promise< int > p1;
499 boost::fibers::fiber( boost::fibers::launch::dispatch, fn1, & p1, 7).detach();
500
501 boost::fibers::shared_future< int > f1 = p1.get_future().share();
502
503 // wait on future
504 BOOST_CHECK( 7 == f1.get() );
505 }
506
507 void test_shared_future_wait_with_fiber_2() {
508 boost::fibers::fiber( boost::fibers::launch::dispatch, fn2).join();
509 }
510
511 void test_shared_future_move() {
512 // future retrieved from promise is valid (if it is the first)
513 boost::fibers::promise< int > p1;
514 boost::fibers::shared_future< int > f1 = p1.get_future().share();
515 BOOST_CHECK( f1.valid() );
516
517 // move construction
518 boost::fibers::shared_future< int > f2( std::move( f1) );
519 BOOST_CHECK( ! f1.valid() );
520 BOOST_CHECK( f2.valid() );
521
522 // move assignment
523 f1 = std::move( f2);
524 BOOST_CHECK( f1.valid() );
525 BOOST_CHECK( ! f2.valid() );
526 }
527
528 void test_shared_future_move_move() {
529 // future retrieved from promise is valid (if it is the first)
530 boost::fibers::promise< A > p1;
531 boost::fibers::shared_future< A > f1 = p1.get_future().share();
532 BOOST_CHECK( f1.valid() );
533
534 // move construction
535 boost::fibers::shared_future< A > f2( std::move( f1) );
536 BOOST_CHECK( ! f1.valid() );
537 BOOST_CHECK( f2.valid() );
538
539 // move assignment
540 f1 = std::move( f2);
541 BOOST_CHECK( f1.valid() );
542 BOOST_CHECK( ! f2.valid() );
543 }
544
545 void test_shared_future_move_ref() {
546 // future retrieved from promise is valid (if it is the first)
547 boost::fibers::promise< int& > p1;
548 boost::fibers::shared_future< int& > f1 = p1.get_future().share();
549 BOOST_CHECK( f1.valid() );
550
551 // move construction
552 boost::fibers::shared_future< int& > f2( std::move( f1) );
553 BOOST_CHECK( ! f1.valid() );
554 BOOST_CHECK( f2.valid() );
555
556 // move assignment
557 f1 = std::move( f2);
558 BOOST_CHECK( f1.valid() );
559 BOOST_CHECK( ! f2.valid() );
560 }
561
562 void test_shared_future_move_void() {
563 // future retrieved from promise is valid (if it is the first)
564 boost::fibers::promise< void > p1;
565 boost::fibers::shared_future< void > f1 = p1.get_future().share();
566 BOOST_CHECK( f1.valid() );
567
568 // move construction
569 boost::fibers::shared_future< void > f2( std::move( f1) );
570 BOOST_CHECK( ! f1.valid() );
571 BOOST_CHECK( f2.valid() );
572
573 // move assignment
574 f1 = std::move( f2);
575 BOOST_CHECK( f1.valid() );
576 BOOST_CHECK( ! f2.valid() );
577 }
578
579
580 boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
581 boost::unit_test_framework::test_suite* test =
582 BOOST_TEST_SUITE("Boost.Fiber: shared_future test suite");
583
584 test->add(BOOST_TEST_CASE(test_shared_future_create));
585 test->add(BOOST_TEST_CASE(test_shared_future_create_ref));
586 test->add(BOOST_TEST_CASE(test_shared_future_create_void));
587 test->add(BOOST_TEST_CASE(test_shared_future_move));
588 test->add(BOOST_TEST_CASE(test_shared_future_move_move));
589 test->add(BOOST_TEST_CASE(test_shared_future_move_ref));
590 test->add(BOOST_TEST_CASE(test_shared_future_move_void));
591 test->add(BOOST_TEST_CASE(test_shared_future_get));
592 test->add(BOOST_TEST_CASE(test_shared_future_get_move));
593 test->add(BOOST_TEST_CASE(test_shared_future_get_ref));
594 test->add(BOOST_TEST_CASE(test_shared_future_get_void));
595 test->add(BOOST_TEST_CASE(test_shared_future_wait));
596 test->add(BOOST_TEST_CASE(test_shared_future_wait_ref));
597 test->add(BOOST_TEST_CASE(test_shared_future_wait_void));
598 test->add(BOOST_TEST_CASE(test_shared_future_wait_for));
599 test->add(BOOST_TEST_CASE(test_shared_future_wait_for_ref));
600 test->add(BOOST_TEST_CASE(test_shared_future_wait_for_void));
601 test->add(BOOST_TEST_CASE(test_shared_future_wait_until));
602 test->add(BOOST_TEST_CASE(test_shared_future_wait_until_ref));
603 test->add(BOOST_TEST_CASE(test_shared_future_wait_until_void));
604 test->add(BOOST_TEST_CASE(test_shared_future_wait_with_fiber_1));
605 test->add(BOOST_TEST_CASE(test_shared_future_wait_with_fiber_2));
606
607 return test;
608 }