]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/fiber/test/test_packaged_task_post.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / fiber / test / test_packaged_task_post.cpp
1 // (C) Copyright 2008-10 Anthony Williams
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6
7 #include <utility>
8 #include <memory>
9 #include <stdexcept>
10 #include <string>
11
12 #include <boost/test/unit_test.hpp>
13
14 #include <boost/fiber/all.hpp>
15
16 int gi = 7;
17
18 struct my_exception : public std::runtime_error {
19 my_exception() :
20 std::runtime_error("my_exception") {
21 }
22 };
23
24 struct A {
25 A() = default;
26
27 A( A const&) = delete;
28 A( A &&) = default;
29
30 A & operator=( A const&) = delete;
31 A & operator=( A &&) = default;
32
33 int value;
34 };
35
36 struct B {
37 bool bset{ false };
38
39 B() = default;
40
41 B( bool set) :
42 bset{ set } {
43 gi = 3;
44 }
45
46 ~B() {
47 if ( bset) {
48 gi = -1;
49 }
50 }
51
52 B( B && other) :
53 bset{ other.bset } {
54 other.bset = false;
55 }
56
57 B & operator=( B && other) {
58 if ( this == & other) return * this;
59 bset = other.bset;
60 other.bset = false;
61 return * this;
62 }
63
64 B( B const&) = delete;
65 B & operator=( B const&) = delete;
66 };
67
68 void fn1( boost::fibers::promise< int > * p, int i) {
69 boost::this_fiber::yield();
70 p->set_value( i);
71 }
72
73 void fn2() {
74 boost::fibers::promise< int > p;
75 boost::fibers::future< int > f( p.get_future() );
76 boost::this_fiber::yield();
77 boost::fibers::fiber( boost::fibers::launch::post, fn1, & p, 7).detach();
78 boost::this_fiber::yield();
79 BOOST_CHECK( 7 == f.get() );
80 }
81
82 int fn3() {
83 return 3;
84 }
85
86 void fn4() {
87 }
88
89 int fn5() {
90 boost::throw_exception( my_exception() );
91 return 3;
92 }
93
94 void fn6() {
95 boost::throw_exception( my_exception() );
96 }
97
98 int & fn7() {
99 return gi;
100 }
101
102 int fn8( int i) {
103 return i;
104 }
105
106 A fn9() {
107 A a;
108 a.value = 3;
109 return a;
110 }
111
112 A fn10() {
113 boost::throw_exception( my_exception() );
114 return A();
115 }
116
117 B fn11( bool set) {
118 B b( set);
119 return b;
120 }
121
122 // packaged_task
123 void test_packaged_task_create() {
124 // default constructed packaged_task is not valid
125 boost::fibers::packaged_task< int() > t1;
126 BOOST_CHECK( ! t1.valid() );
127
128 // packaged_task from function
129 boost::fibers::packaged_task< int() > t2( fn3);
130 BOOST_CHECK( t2.valid() );
131 }
132
133 // packaged_task
134 void test_packaged_task_create_move() {
135 // default constructed packaged_task is not valid
136 boost::fibers::packaged_task< A() > t1;
137 BOOST_CHECK( ! t1.valid() );
138
139 // packaged_task from function
140 boost::fibers::packaged_task< A() > t2( fn9);
141 BOOST_CHECK( t2.valid() );
142 }
143
144 void test_packaged_task_create_void() {
145 // default constructed packaged_task is not valid
146 boost::fibers::packaged_task< void() > t1;
147 BOOST_CHECK( ! t1.valid() );
148
149 // packaged_task from function
150 boost::fibers::packaged_task< void() > t2( fn4);
151 BOOST_CHECK( t2.valid() );
152 }
153
154 void test_packaged_task_move() {
155 boost::fibers::packaged_task< int() > t1( fn3);
156 BOOST_CHECK( t1.valid() );
157
158 // move construction
159 boost::fibers::packaged_task< int() > t2( std::move( t1) );
160 BOOST_CHECK( ! t1.valid() );
161 BOOST_CHECK( t2.valid() );
162
163 // move assignment
164 t1 = std::move( t2);
165 BOOST_CHECK( t1.valid() );
166 BOOST_CHECK( ! t2.valid() );
167 }
168
169 void test_packaged_task_move_move() {
170 boost::fibers::packaged_task< A() > t1( fn9);
171 BOOST_CHECK( t1.valid() );
172
173 // move construction
174 boost::fibers::packaged_task< A() > t2( std::move( t1) );
175 BOOST_CHECK( ! t1.valid() );
176 BOOST_CHECK( t2.valid() );
177
178 // move assignment
179 t1 = std::move( t2);
180 BOOST_CHECK( t1.valid() );
181 BOOST_CHECK( ! t2.valid() );
182 }
183
184 void test_packaged_task_move_void() {
185 boost::fibers::packaged_task< void() > t1( fn4);
186 BOOST_CHECK( t1.valid() );
187
188 // move construction
189 boost::fibers::packaged_task< void() > t2( std::move( t1) );
190 BOOST_CHECK( ! t1.valid() );
191 BOOST_CHECK( t2.valid() );
192
193 // move assignment
194 t1 = std::move( t2);
195 BOOST_CHECK( t1.valid() );
196 BOOST_CHECK( ! t2.valid() );
197 }
198
199 void test_packaged_task_swap() {
200 boost::fibers::packaged_task< int() > t1( fn3);
201 BOOST_CHECK( t1.valid() );
202
203 boost::fibers::packaged_task< int() > t2;
204 BOOST_CHECK( ! t2.valid() );
205
206 // swap
207 t1.swap( t2);
208 BOOST_CHECK( ! t1.valid() );
209 BOOST_CHECK( t2.valid() );
210 }
211
212 void test_packaged_task_swap_move() {
213 boost::fibers::packaged_task< A() > t1( fn9);
214 BOOST_CHECK( t1.valid() );
215
216 boost::fibers::packaged_task< A() > t2;
217 BOOST_CHECK( ! t2.valid() );
218
219 // swap
220 t1.swap( t2);
221 BOOST_CHECK( ! t1.valid() );
222 BOOST_CHECK( t2.valid() );
223 }
224
225 void test_packaged_task_swap_void() {
226 boost::fibers::packaged_task< void() > t1( fn4);
227 BOOST_CHECK( t1.valid() );
228
229 boost::fibers::packaged_task< void() > t2;
230 BOOST_CHECK( ! t2.valid() );
231
232 // swap
233 t1.swap( t2);
234 BOOST_CHECK( ! t1.valid() );
235 BOOST_CHECK( t2.valid() );
236 }
237
238 void test_packaged_task_reset() {
239 {
240 boost::fibers::packaged_task< int() > p( fn3);
241 boost::fibers::future< int > f( p.get_future() );
242 BOOST_CHECK( p.valid() );
243
244 p();
245 BOOST_CHECK( 3 == f.get() );
246
247 // reset
248 p.reset();
249 p();
250 f = p.get_future();
251 BOOST_CHECK( 3 == f.get() );
252 }
253 {
254 boost::fibers::packaged_task< int() > p;
255
256 bool thrown = false;
257 try {
258 p.reset();
259 } catch ( boost::fibers::packaged_task_uninitialized const&) {
260 thrown = true;
261 }
262 BOOST_CHECK( thrown);
263 }
264 }
265
266 void test_packaged_task_reset_destruction() {
267 gi = 0;
268 boost::fibers::packaged_task< B( bool) > p( fn11);
269 BOOST_CHECK( p.valid() );
270
271 BOOST_CHECK( 0 == gi);
272 p( true);
273 BOOST_CHECK( 3 == gi);
274
275 // reset
276 p.reset();
277 BOOST_CHECK( -1 == gi);
278 p( false);
279 BOOST_CHECK( 3 == gi);
280
281 // reset
282 p.reset();
283 BOOST_CHECK( 3 == gi);
284 }
285
286 void test_packaged_task_reset_move() {
287 {
288 boost::fibers::packaged_task< A() > p( fn9);
289 boost::fibers::future< A > f( p.get_future() );
290 BOOST_CHECK( p.valid() );
291
292 p();
293 BOOST_CHECK( 3 == f.get().value);
294
295 // reset
296 p.reset();
297 p();
298 f = p.get_future();
299 BOOST_CHECK( 3 == f.get().value);
300 }
301 {
302 boost::fibers::packaged_task< A() > p;
303
304 bool thrown = false;
305 try {
306 p.reset();
307 } catch ( boost::fibers::packaged_task_uninitialized const&) {
308 thrown = true;
309 }
310 BOOST_CHECK( thrown);
311 }
312 }
313
314 void test_packaged_task_reset_void() {
315 {
316 boost::fibers::packaged_task< void() > p( fn4);
317 boost::fibers::future< void > f( p.get_future() );
318 BOOST_CHECK( p.valid() );
319
320 p();
321 f.get();
322
323 // reset
324 p.reset();
325 p();
326 f = p.get_future();
327 f.get();
328 }
329 {
330 boost::fibers::packaged_task< void() > p;
331
332 bool thrown = false;
333 try {
334 p.reset();
335 } catch ( boost::fibers::packaged_task_uninitialized const&) {
336 thrown = true;
337 }
338 BOOST_CHECK( thrown);
339 }
340 }
341
342 void test_packaged_task_get_future() {
343 boost::fibers::packaged_task< int() > t1( fn3);
344 BOOST_CHECK( t1.valid() );
345
346 // retrieve future
347 boost::fibers::future< int > f1 = t1.get_future();
348 BOOST_CHECK( f1.valid() );
349
350 // retrieve future a second time
351 bool thrown = false;
352 try {
353 f1 = t1.get_future();
354 } catch ( boost::fibers::future_already_retrieved const&) {
355 thrown = true;
356 }
357 BOOST_CHECK( thrown);
358
359 // move construction
360 boost::fibers::packaged_task< int() > t2( std::move( t1) );
361 BOOST_CHECK( ! t1.valid() );
362 BOOST_CHECK( t2.valid() );
363
364 // retrieve future from uninitialized
365 thrown = false;
366 try {
367 f1 = t1.get_future();
368 } catch ( boost::fibers::packaged_task_uninitialized const&) {
369 thrown = true;
370 }
371 BOOST_CHECK( thrown);
372 }
373
374 void test_packaged_task_get_future_move() {
375 boost::fibers::packaged_task< A() > t1( fn9);
376 BOOST_CHECK( t1.valid() );
377
378 // retrieve future
379 boost::fibers::future< A > f1 = t1.get_future();
380 BOOST_CHECK( f1.valid() );
381
382 // retrieve future a second time
383 bool thrown = false;
384 try {
385 f1 = t1.get_future();
386 } catch ( boost::fibers::future_already_retrieved const&) {
387 thrown = true;
388 }
389 BOOST_CHECK( thrown);
390
391 // move construction
392 boost::fibers::packaged_task< A() > t2( std::move( t1) );
393 BOOST_CHECK( ! t1.valid() );
394 BOOST_CHECK( t2.valid() );
395
396 // retrieve future from uninitialized
397 thrown = false;
398 try {
399 f1 = t1.get_future();
400 } catch ( boost::fibers::packaged_task_uninitialized const&) {
401 thrown = true;
402 }
403 BOOST_CHECK( thrown);
404 }
405
406 void test_packaged_task_get_future_void() {
407 boost::fibers::packaged_task< void() > t1( fn4);
408 BOOST_CHECK( t1.valid() );
409
410 // retrieve future
411 boost::fibers::future< void > f1 = t1.get_future();
412 BOOST_CHECK( f1.valid() );
413
414 // retrieve future a second time
415 bool thrown = false;
416 try {
417 f1 = t1.get_future();
418 } catch ( boost::fibers::future_already_retrieved const&) {
419 thrown = true;
420 }
421 BOOST_CHECK( thrown);
422
423 // move construction
424 boost::fibers::packaged_task< void() > t2( std::move( t1) );
425 BOOST_CHECK( ! t1.valid() );
426 BOOST_CHECK( t2.valid() );
427
428 // retrieve future from uninitialized
429 thrown = false;
430 try {
431 f1 = t1.get_future();
432 } catch ( boost::fibers::packaged_task_uninitialized const&) {
433 thrown = true;
434 }
435 BOOST_CHECK( thrown);
436 }
437
438 void test_packaged_task_exec() {
439 // promise takes a copyable as return type
440 boost::fibers::packaged_task< int() > t1( fn3);
441 BOOST_CHECK( t1.valid() );
442 boost::fibers::future< int > f1 = t1.get_future();
443 BOOST_CHECK( f1.valid() );
444
445 // exec
446 t1();
447 BOOST_CHECK( 3 == f1.get() );
448
449 // exec a second time
450 bool thrown = false;
451 try {
452 t1();
453 } catch ( boost::fibers::promise_already_satisfied const&) {
454 thrown = true;
455 }
456 BOOST_CHECK( thrown);
457 }
458
459 void test_packaged_task_exec_move() {
460 // promise takes a copyable as return type
461 boost::fibers::packaged_task< A() > t1( fn9);
462 BOOST_CHECK( t1.valid() );
463 boost::fibers::future< A > f1 = t1.get_future();
464 BOOST_CHECK( f1.valid() );
465
466 // exec
467 t1();
468 BOOST_CHECK( 3 == f1.get().value);
469
470 // exec a second time
471 bool thrown = false;
472 try {
473 t1();
474 } catch ( boost::fibers::promise_already_satisfied const&) {
475 thrown = true;
476 }
477 BOOST_CHECK( thrown);
478 }
479
480 void test_packaged_task_exec_param() {
481 // promise takes a copyable as return type
482 boost::fibers::packaged_task< int( int) > t1( fn8);
483 BOOST_CHECK( t1.valid() );
484 boost::fibers::future< int > f1 = t1.get_future();
485 BOOST_CHECK( f1.valid() );
486
487 // exec
488 t1( 3);
489 BOOST_CHECK( 3 == f1.get() );
490
491 // exec a second time
492 bool thrown = false;
493 try {
494 t1( 7);
495 } catch ( boost::fibers::promise_already_satisfied const&) {
496 thrown = true;
497 }
498 BOOST_CHECK( thrown);
499
500 //TODO: packaged_task returns a moveable-only as return type
501 }
502
503 void test_packaged_task_exec_ref() {
504 // promise takes a copyable as return type
505 boost::fibers::packaged_task< int&() > t1( fn7);
506 BOOST_CHECK( t1.valid() );
507 boost::fibers::future< int& > f1 = t1.get_future();
508 BOOST_CHECK( f1.valid() );
509
510 // exec
511 t1();
512 int & i = f1.get();
513 BOOST_CHECK( &gi == &i);
514
515 // exec a second time
516 bool thrown = false;
517 try {
518 t1();
519 } catch ( boost::fibers::promise_already_satisfied const&) {
520 thrown = true;
521 }
522 BOOST_CHECK( thrown);
523
524 //TODO: packaged_task returns a moveable-only as return type
525 }
526
527 void test_packaged_task_exec_void() {
528 // promise takes a copyable as return type
529 boost::fibers::packaged_task< void() > t1( fn4);
530 BOOST_CHECK( t1.valid() );
531 boost::fibers::future< void > f1 = t1.get_future();
532 BOOST_CHECK( f1.valid() );
533
534 // set void
535 t1();
536 f1.get();
537
538 // exec a second time
539 bool thrown = false;
540 try {
541 t1();
542 } catch ( boost::fibers::promise_already_satisfied const&) {
543 thrown = true;
544 }
545 BOOST_CHECK( thrown);
546 }
547
548 void test_packaged_task_exception() {
549 // promise takes a copyable as return type
550 boost::fibers::packaged_task< int() > t1( fn5);
551 BOOST_CHECK( t1.valid() );
552 boost::fibers::future< int > f1 = t1.get_future();
553 BOOST_CHECK( f1.valid() );
554
555 // exec
556 t1();
557 bool thrown = false;
558 try {
559 f1.get();
560 } catch ( my_exception const&) {
561 thrown = true;
562 }
563 BOOST_CHECK( thrown);
564
565 boost::fibers::packaged_task< int() > t2( fn5);
566 BOOST_CHECK( t2.valid() );
567 boost::fibers::future< int > f2 = t2.get_future();
568 BOOST_CHECK( f2.valid() );
569
570 // exec
571 t2();
572 BOOST_CHECK( f2.get_exception_ptr() );
573 thrown = false;
574 try
575 { std::rethrow_exception( f2.get_exception_ptr() ); }
576 catch ( my_exception const&)
577 { thrown = true; }
578 BOOST_CHECK( thrown);
579 }
580
581 void test_packaged_task_exception_move() {
582 // promise takes a moveable as return type
583 boost::fibers::packaged_task< A() > t1( fn10);
584 BOOST_CHECK( t1.valid() );
585 boost::fibers::future< A > f1 = t1.get_future();
586 BOOST_CHECK( f1.valid() );
587
588 // exec
589 t1();
590 bool thrown = false;
591 try {
592 f1.get();
593 } catch ( my_exception const&) {
594 thrown = true;
595 }
596 BOOST_CHECK( thrown);
597
598 boost::fibers::packaged_task< A() > t2( fn10);
599 BOOST_CHECK( t2.valid() );
600 boost::fibers::future< A > f2 = t2.get_future();
601 BOOST_CHECK( f2.valid() );
602
603 // exec
604 t2();
605 BOOST_CHECK( f2.get_exception_ptr() );
606 thrown = false;
607 try
608 { std::rethrow_exception( f2.get_exception_ptr() ); }
609 catch ( my_exception const&)
610 { thrown = true; }
611 BOOST_CHECK( thrown);
612 }
613
614 void test_packaged_task_exception_void() {
615 // promise takes a copyable as return type
616 boost::fibers::packaged_task< void() > t1( fn6);
617 BOOST_CHECK( t1.valid() );
618 boost::fibers::future< void > f1 = t1.get_future();
619 BOOST_CHECK( f1.valid() );
620
621 // set void
622 t1();
623 bool thrown = false;
624 try {
625 f1.get();
626 } catch ( my_exception const&) {
627 thrown = true;
628 }
629 BOOST_CHECK( thrown);
630
631 boost::fibers::packaged_task< void() > t2( fn6);
632 BOOST_CHECK( t2.valid() );
633 boost::fibers::future< void > f2 = t2.get_future();
634 BOOST_CHECK( f2.valid() );
635
636 // exec
637 t2();
638 BOOST_CHECK( f2.get_exception_ptr() );
639 thrown = false;
640 try {
641 std::rethrow_exception( f2.get_exception_ptr() );
642 } catch ( my_exception const&) {
643 thrown = true;
644 }
645 BOOST_CHECK( thrown);
646 }
647
648
649 boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
650 boost::unit_test_framework::test_suite* test =
651 BOOST_TEST_SUITE("Boost.Fiber: packaged_task test suite");
652
653 test->add(BOOST_TEST_CASE(test_packaged_task_create));
654 test->add(BOOST_TEST_CASE(test_packaged_task_create_move));
655 test->add(BOOST_TEST_CASE(test_packaged_task_create_void));
656 test->add(BOOST_TEST_CASE(test_packaged_task_move));
657 test->add(BOOST_TEST_CASE(test_packaged_task_move_move));
658 test->add(BOOST_TEST_CASE(test_packaged_task_move_void));
659 test->add(BOOST_TEST_CASE(test_packaged_task_swap));
660 test->add(BOOST_TEST_CASE(test_packaged_task_swap_move));
661 test->add(BOOST_TEST_CASE(test_packaged_task_swap_void));
662 test->add(BOOST_TEST_CASE(test_packaged_task_reset));
663 test->add(BOOST_TEST_CASE(test_packaged_task_reset_destruction));
664 test->add(BOOST_TEST_CASE(test_packaged_task_reset_move));
665 test->add(BOOST_TEST_CASE(test_packaged_task_reset_void));
666 test->add(BOOST_TEST_CASE(test_packaged_task_get_future));
667 test->add(BOOST_TEST_CASE(test_packaged_task_get_future_move));
668 test->add(BOOST_TEST_CASE(test_packaged_task_get_future_void));
669 test->add(BOOST_TEST_CASE(test_packaged_task_exec));
670 test->add(BOOST_TEST_CASE(test_packaged_task_exec_move));
671 test->add(BOOST_TEST_CASE(test_packaged_task_exec_param));
672 test->add(BOOST_TEST_CASE(test_packaged_task_exec_ref));
673 test->add(BOOST_TEST_CASE(test_packaged_task_exec_void));
674 test->add(BOOST_TEST_CASE(test_packaged_task_exception));
675 test->add(BOOST_TEST_CASE(test_packaged_task_exception_move));
676 test->add(BOOST_TEST_CASE(test_packaged_task_exception_void));
677
678 return test;
679 }