• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
my_exceptionmy_exception19     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{ 0 };
34 };
35 
fn1(boost::fibers::promise<int> * p,int i)36 void fn1( boost::fibers::promise< int > * p, int i) {
37     boost::this_fiber::yield();
38     p->set_value( i);
39 }
40 
fn2()41 void fn2() {
42     boost::fibers::promise< int > p;
43     boost::fibers::future< int > f( p.get_future() );
44     boost::this_fiber::yield();
45     boost::fibers::fiber( boost::fibers::launch::post, fn1, & p, 7).detach();
46     boost::this_fiber::yield();
47     BOOST_CHECK( 7 == f.get() );
48 }
49 
fn3()50 int fn3() {
51     return 3;
52 }
53 
fn4()54 void fn4() {
55 }
56 
fn5()57 int fn5() {
58     boost::throw_exception( my_exception() );
59     return 3;
60 }
61 
fn6()62 void fn6() {
63     boost::throw_exception( my_exception() );
64 }
65 
fn7()66 int & fn7() {
67     return gi;
68 }
69 
fn8(int i)70 int fn8( int i) {
71     return i;
72 }
73 
fn9()74 A fn9() {
75      A a;
76      a.value = 3;
77      return a;
78 }
79 
fn10()80 A fn10() {
81     boost::throw_exception( my_exception() );
82     return A();
83 }
84 
85 // promise
test_promise_create()86 void test_promise_create() {
87     // use std::allocator<> as default
88     boost::fibers::promise< int > p1;
89 
90     // use std::allocator<> as user defined
91     std::allocator< boost::fibers::promise< int > > alloc;
92     boost::fibers::promise< int > p2( std::allocator_arg,  alloc);
93 }
94 
test_promise_create_ref()95 void test_promise_create_ref() {
96     // use std::allocator<> as default
97     boost::fibers::promise< int& > p1;
98 
99     // use std::allocator<> as user defined
100     std::allocator< boost::fibers::promise< int& > > alloc;
101     boost::fibers::promise< int& > p2( std::allocator_arg, alloc);
102 }
103 
test_promise_create_void()104 void test_promise_create_void() {
105     // use std::allocator<> as default
106     boost::fibers::promise< void > p1;
107 
108     // use std::allocator<> as user defined
109     std::allocator< boost::fibers::promise< void > > alloc;
110     boost::fibers::promise< void > p2( std::allocator_arg, alloc);
111 }
112 
test_promise_move()113 void test_promise_move() {
114     boost::fibers::promise< int > p1;
115 
116     // move construction
117     boost::fibers::promise< int > p2( std::move( p1) );
118 
119     // move assigment
120     p1 = std::move( p2);
121 }
122 
test_promise_move_ref()123 void test_promise_move_ref() {
124     boost::fibers::promise< int& > p1;
125 
126     // move construction
127     boost::fibers::promise< int& > p2( std::move( p1) );
128 
129     // move assigment
130     p1 = std::move( p2);
131 }
132 
test_promise_move_void()133 void test_promise_move_void() {
134     boost::fibers::promise< void > p1;
135 
136     // move construction
137     boost::fibers::promise< void > p2( std::move( p1) );
138 
139     // move assigment
140     p1 = std::move( p2);
141 }
142 
test_promise_swap()143 void test_promise_swap() {
144     boost::fibers::promise< int > p1;
145 
146     // move construction
147     boost::fibers::promise< int > p2( std::move( p1) );
148 
149     // swap
150     p1.swap( p2);
151 }
152 
test_promise_swap_ref()153 void test_promise_swap_ref() {
154     boost::fibers::promise< int& > p1;
155 
156     // move construction
157     boost::fibers::promise< int& > p2( std::move( p1) );
158 
159     // swap
160     p1.swap( p2);
161 }
162 
test_promise_swap_void()163 void test_promise_swap_void() {
164     boost::fibers::promise< void > p1;
165 
166     // move construction
167     boost::fibers::promise< void > p2( std::move( p1) );
168 
169     // swap
170     p1.swap( p2);
171 }
172 
test_promise_get_future()173 void test_promise_get_future() {
174     boost::fibers::promise< int > p1;
175 
176     // retrieve future
177     boost::fibers::future< int > f1 = p1.get_future();
178     BOOST_CHECK( f1.valid() );
179 
180     // retrieve future a second time
181     bool thrown = false;
182     try {
183         f1 = p1.get_future();
184     } catch ( boost::fibers::future_already_retrieved const&) {
185         thrown = true;
186     }
187     BOOST_CHECK( thrown);
188 
189     // move construction
190     boost::fibers::promise< int > p2( std::move( p1) );
191 
192     // retrieve future from uninitialized
193     thrown = false;
194     try {
195         f1 = p1.get_future();
196     } catch ( boost::fibers::promise_uninitialized const&) {
197         thrown = true;
198     }
199     BOOST_CHECK( thrown);
200 }
201 
test_promise_get_future_ref()202 void test_promise_get_future_ref() {
203     boost::fibers::promise< int& > p1;
204 
205     // retrieve future
206     boost::fibers::future< int& > f1 = p1.get_future();
207     BOOST_CHECK( f1.valid() );
208 
209     // retrieve future a second time
210     bool thrown = false;
211     try {
212         f1 = p1.get_future();
213     } catch ( boost::fibers::future_already_retrieved const&) {
214         thrown = true;
215     }
216     BOOST_CHECK( thrown);
217 
218     // move construction
219     boost::fibers::promise< int& > p2( std::move( p1) );
220 
221     // retrieve future from uninitialized
222     thrown = false;
223     try {
224         f1 = p1.get_future();
225     } catch ( boost::fibers::promise_uninitialized const&) {
226         thrown = true;
227     }
228     BOOST_CHECK( thrown);
229 }
230 
test_promise_get_future_void()231 void test_promise_get_future_void() {
232     boost::fibers::promise< void > p1;
233 
234     // retrieve future
235     boost::fibers::future< void > f1 = p1.get_future();
236     BOOST_CHECK( f1.valid() );
237 
238     // retrieve future a second time
239     bool thrown = false;
240     try {
241         f1 = p1.get_future();
242     } catch ( boost::fibers::future_already_retrieved const&) {
243         thrown = true;
244     }
245     BOOST_CHECK( thrown);
246 
247     // move construction
248     boost::fibers::promise< void > p2( std::move( p1) );
249 
250     // retrieve future from uninitialized
251     thrown = false;
252     try {
253         f1 = p1.get_future();
254     } catch ( boost::fibers::promise_uninitialized const&) {
255         thrown = true;
256     }
257     BOOST_CHECK( thrown);
258 }
259 
test_promise_set_value()260 void test_promise_set_value() {
261     // promise takes a copyable as return type
262     boost::fibers::promise< int > p1;
263     boost::fibers::future< int > f1 = p1.get_future();
264     BOOST_CHECK( f1.valid() );
265 
266     // copy value
267     p1.set_value( 7);
268     BOOST_CHECK( 7 == f1.get() );
269 
270     // set value a second time
271     bool thrown = false;
272     try {
273         p1.set_value( 11);
274     } catch ( boost::fibers::promise_already_satisfied const&) {
275         thrown = true;
276     }
277     BOOST_CHECK( thrown);
278 }
279 
test_promise_set_value_move()280 void test_promise_set_value_move() {
281     // promise takes a copyable as return type
282     boost::fibers::promise< A > p1;
283     boost::fibers::future< A > f1 = p1.get_future();
284     BOOST_CHECK( f1.valid() );
285 
286     // move value
287     A a1; a1.value = 7;
288     p1.set_value( std::move( a1) );
289     A a2 = f1.get();
290     BOOST_CHECK( 7 == a2.value);
291 
292     // set value a second time
293     bool thrown = false;
294     try {
295         A a;
296         p1.set_value( std::move( a) );
297     } catch ( boost::fibers::promise_already_satisfied const&) {
298         thrown = true;
299     }
300     BOOST_CHECK( thrown);
301 }
302 
test_promise_set_value_ref()303 void test_promise_set_value_ref() {
304     // promise takes a reference as return type
305     boost::fibers::promise< int& > p1;
306     boost::fibers::future< int& > f1 = p1.get_future();
307     BOOST_CHECK( f1.valid() );
308 
309     // copy value
310     int i = 7;
311     p1.set_value( i);
312     int & j = f1.get();
313     BOOST_CHECK( &i == &j);
314 
315     // set value a second time
316     bool thrown = false;
317     try {
318         p1.set_value( i);
319     } catch ( boost::fibers::promise_already_satisfied const&) {
320         thrown = true;
321     }
322     BOOST_CHECK( thrown);
323 }
324 
test_promise_set_value_void()325 void test_promise_set_value_void() {
326     // promise takes a copyable as return type
327     boost::fibers::promise< void > p1;
328     boost::fibers::future< void > f1 = p1.get_future();
329     BOOST_CHECK( f1.valid() );
330 
331     // set void
332     p1.set_value();
333     f1.get();
334 
335     // set value a second time
336     bool thrown = false;
337     try {
338         p1.set_value();
339     } catch ( boost::fibers::promise_already_satisfied const&) {
340         thrown = true;
341     }
342     BOOST_CHECK( thrown);
343 }
344 
test_promise_set_exception()345 void test_promise_set_exception() {
346     boost::fibers::promise< int > p1;
347     boost::fibers::future< int > f1 = p1.get_future();
348     BOOST_CHECK( f1.valid() );
349     p1.set_exception( std::make_exception_ptr( my_exception() ) );
350 
351     // set exception a second time
352     bool thrown = false;
353     try {
354         p1.set_exception( std::make_exception_ptr( my_exception() ) );
355     } catch ( boost::fibers::promise_already_satisfied const&) {
356         thrown = true;
357     }
358     BOOST_CHECK( thrown);
359 
360     // set value
361     thrown = false;
362     try
363     { p1.set_value( 11); }
364     catch ( boost::fibers::promise_already_satisfied const&)
365     { thrown = true; }
366     BOOST_CHECK( thrown);
367 }
368 
test_promise_set_exception_ref()369 void test_promise_set_exception_ref() {
370     boost::fibers::promise< int& > p1;
371     boost::fibers::future< int& > f1 = p1.get_future();
372     BOOST_CHECK( f1.valid() );
373     p1.set_exception( std::make_exception_ptr( my_exception() ) );
374 
375     // set exception a second time
376     bool thrown = false;
377     try {
378         p1.set_exception( std::make_exception_ptr( my_exception() ) );
379     } catch ( boost::fibers::promise_already_satisfied const&) {
380         thrown = true;
381     }
382     BOOST_CHECK( thrown);
383 
384     // set value
385     thrown = false;
386     int i = 11;
387     try {
388         p1.set_value( i);
389     } catch ( boost::fibers::promise_already_satisfied const&) {
390         thrown = true;
391     }
392     BOOST_CHECK( thrown);
393 }
394 
test_promise_set_exception_void()395 void test_promise_set_exception_void() {
396     boost::fibers::promise< void > p1;
397     boost::fibers::future< void > f1 = p1.get_future();
398     BOOST_CHECK( f1.valid() );
399     p1.set_exception( std::make_exception_ptr( my_exception() ) );
400 
401     // set exception a second time
402     bool thrown = false;
403     try {
404         p1.set_exception( std::make_exception_ptr( my_exception() ) );
405     } catch ( boost::fibers::promise_already_satisfied const&) {
406         thrown = true;
407     }
408     BOOST_CHECK( thrown);
409 
410     // set value
411     thrown = false;
412     try {
413         p1.set_value();
414     } catch ( boost::fibers::promise_already_satisfied const&) {
415         thrown = true;
416     }
417     BOOST_CHECK( thrown);
418 }
419 
init_unit_test_suite(int,char * [])420 boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
421     boost::unit_test_framework::test_suite* test =
422         BOOST_TEST_SUITE("Boost.Fiber: promise test suite");
423 
424     test->add(BOOST_TEST_CASE(test_promise_create));
425     test->add(BOOST_TEST_CASE(test_promise_create_ref));
426     test->add(BOOST_TEST_CASE(test_promise_create_void));
427     test->add(BOOST_TEST_CASE(test_promise_move));
428     test->add(BOOST_TEST_CASE(test_promise_move_ref));
429     test->add(BOOST_TEST_CASE(test_promise_move_void));
430     test->add(BOOST_TEST_CASE(test_promise_swap));
431     test->add(BOOST_TEST_CASE(test_promise_swap_ref));
432     test->add(BOOST_TEST_CASE(test_promise_swap_void));
433     test->add(BOOST_TEST_CASE(test_promise_get_future));
434     test->add(BOOST_TEST_CASE(test_promise_get_future_ref));
435     test->add(BOOST_TEST_CASE(test_promise_get_future_void));
436     test->add(BOOST_TEST_CASE(test_promise_set_value));
437     test->add(BOOST_TEST_CASE(test_promise_set_value_move));
438     test->add(BOOST_TEST_CASE(test_promise_set_value_ref));
439     test->add(BOOST_TEST_CASE(test_promise_set_value_void));
440     test->add(BOOST_TEST_CASE(test_promise_set_exception));
441     test->add(BOOST_TEST_CASE(test_promise_set_exception_ref));
442     test->add(BOOST_TEST_CASE(test_promise_set_exception_void));
443 
444     return test;
445 }
446