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