]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/leaf/test/capture_exception_result_async_test.cpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / leaf / test / capture_exception_result_async_test.cpp
1 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
2
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #include <boost/leaf/detail/config.hpp>
7 #if defined(BOOST_LEAF_NO_EXCEPTIONS) || defined(BOOST_LEAF_NO_THREADS)
8
9 #include <iostream>
10
11 int main()
12 {
13 std::cout << "Unit test not applicable." << std::endl;
14 return 0;
15 }
16
17 #else
18
19 #include <boost/leaf/capture.hpp>
20 #include <boost/leaf/result.hpp>
21 #include <boost/leaf/handle_errors.hpp>
22
23 #include "lightweight_test.hpp"
24 #include <vector>
25 #include <future>
26 #include <iterator>
27 #include <algorithm>
28
29 namespace leaf = boost::leaf;
30
31 template <int> struct info { int value; };
32
33 struct fut_info
34 {
35 int a;
36 int b;
37 int result;
38 std::future<leaf::result<int>> fut;
39 };
40
41 template <class H, class F>
42 std::vector<fut_info> launch_tasks( int task_count, F f )
43 {
44 BOOST_LEAF_ASSERT(task_count>0);
45 std::vector<fut_info> fut;
46 std::generate_n( std::back_inserter(fut), task_count,
47 [=]
48 {
49 int const a = rand();
50 int const b = rand();
51 int const res = (rand()%10) - 5;
52 return fut_info { a, b, res, std::async( std::launch::async,
53 [=]
54 {
55 return leaf::capture(leaf::make_shared_context<H>(), f, a, b, res);
56 } ) };
57 } );
58 return fut;
59 }
60
61 int main()
62 {
63 int received_a, received_b;
64 auto error_handlers = std::make_tuple(
65 [&]( info<1> const & x1, info<2> const & x2, info<4> const & )
66 {
67 received_a = x1.value;
68 received_b = x2.value;
69 return -1;
70 },
71 []
72 {
73 return -2;
74 } );
75
76 {
77 std::vector<fut_info> fut = launch_tasks<decltype(error_handlers)>(
78 100,
79 []( int a, int b, int res ) -> leaf::result<int>
80 {
81 if( res >= 0 )
82 return res;
83 else
84 return leaf::new_error( info<1>{a}, info<2>{b}, info<3>{} );
85 } );
86
87 for( auto & f : fut )
88 {
89 f.fut.wait();
90 received_a = received_b = 0;
91 int r = leaf::try_handle_all(
92 [&]
93 {
94 auto load = leaf::on_error( info<4>{} );
95
96 // Calling future_get is required in order to make the on_error (above) work.
97 return leaf::future_get(f.fut);
98 },
99 error_handlers );
100 if( f.result>=0 )
101 BOOST_TEST_EQ(r, f.result);
102 else
103 {
104 BOOST_TEST_EQ(r, -1);
105 BOOST_TEST_EQ(received_a, f.a);
106 BOOST_TEST_EQ(received_b, f.b);
107 }
108 }
109 }
110
111 {
112 std::vector<fut_info> fut = launch_tasks<decltype(error_handlers)>(
113 100,
114 []( int a, int b, int res ) -> leaf::result<int>
115 {
116 if( res >= 0 )
117 return res;
118 else
119 return leaf::new_error( info<1>{a}, info<2>{b}, info<3>{} );
120 } );
121
122 for( auto & f : fut )
123 {
124 f.fut.wait();
125 received_a = received_b = 0;
126 int r = leaf::try_handle_all(
127 [&]
128 {
129 auto load = leaf::on_error( info<4>{} );
130
131 return leaf::try_handle_some(
132 [&]
133 {
134 // Not calling future_get, a on_error in this scope won't work correctly.
135 // This is to verify that the on_error in the outer scope (above) works.
136 return f.fut.get();
137 },
138 []( leaf::error_info const & err )
139 {
140 return err.error();
141 } );
142 },
143 error_handlers );
144 if( f.result>=0 )
145 BOOST_TEST_EQ(r, f.result);
146 else
147 {
148 BOOST_TEST_EQ(r, -1);
149 BOOST_TEST_EQ(received_a, f.a);
150 BOOST_TEST_EQ(received_b, f.b);
151 }
152 }
153 }
154
155 return boost::report_errors();
156 }
157
158 #endif