• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
my_exceptionmy_exception24     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 
fn1(boost::fibers::promise<int> * p,int i)41 void fn1( boost::fibers::promise< int > * p, int i) {
42     boost::this_fiber::yield();
43     p->set_value( i);
44 }
45 
fn2()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 
fn3()55 int fn3() {
56     return 3;
57 }
58 
fn4()59 void fn4() {
60 }
61 
fn5()62 int fn5() {
63     boost::throw_exception( my_exception() );
64     return 3;
65 }
66 
fn6()67 void fn6() {
68     boost::throw_exception( my_exception() );
69 }
70 
fn7()71 int & fn7() {
72     return gi;
73 }
74 
fn8(int i)75 int fn8( int i) {
76     return i;
77 }
78 
fn9()79 A fn9() {
80      A a;
81      a.value = 3;
82      return a;
83 }
84 
fn10()85 A fn10() {
86     boost::throw_exception( my_exception() );
87     return A();
88 }
89 
fn11(boost::fibers::promise<int> p)90 void fn11( boost::fibers::promise< int > p) {
91   boost::this_fiber::sleep_for( ms(500) );
92   p.set_value(3);
93 }
94 
fn12(boost::fibers::promise<int &> p)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 
fn13(boost::fibers::promise<void> p)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
test_shared_future_create()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 
test_shared_future_create_ref()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 
test_shared_future_create_void()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 
test_shared_future_get()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 
test_shared_future_get_move()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 
test_shared_future_get_ref()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 
test_shared_future_get_void()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 
test_future_share()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 
test_future_share_ref()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 
test_future_share_void()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 
test_shared_future_wait()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 
test_shared_future_wait_ref()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 
test_shared_future_wait_void()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 
test_shared_future_wait_for()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 
test_shared_future_wait_for_ref()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 
test_shared_future_wait_for_void()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 
test_shared_future_wait_until()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 
test_shared_future_wait_until_ref()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 
test_shared_future_wait_until_void()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 
test_shared_future_wait_with_fiber_1()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 
test_shared_future_wait_with_fiber_2()507 void test_shared_future_wait_with_fiber_2() {
508     boost::fibers::fiber( boost::fibers::launch::dispatch, fn2).join();
509 }
510 
test_shared_future_move()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 
test_shared_future_move_move()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 
test_shared_future_move_ref()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 
test_shared_future_move_void()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 
init_unit_test_suite(int,char * [])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 }
609