]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/leaf/examples/error_trace.cpp
buildsys: change download over to reef release
[ceph.git] / ceph / src / boost / libs / leaf / examples / error_trace.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 // This program demonstrates the use of leaf::on_error to capture the path an error takes
7 // as is bubbles up the call stack. The error path-capturing code only runs if:
8 // - An error occurs, and
9 // - A handler that takes e_error_trace argument is present.
10 // Otherwise none of the error trace machinery will be invoked by LEAF.
11
12 // This example is similar to error_log, except the path the error takes is recorded in
13 // a std::deque, rather than just printed in-place.
14
15 #include <boost/leaf/on_error.hpp>
16 #include <boost/leaf/handle_errors.hpp>
17 #include <boost/leaf/result.hpp>
18 #include <iostream>
19 #include <deque>
20 #include <cstdlib>
21
22 #define ENABLE_ERROR_TRACE 1
23
24 namespace leaf = boost::leaf;
25
26 // The error trace is activated only if an error-handling scope provides a handler for e_error_trace.
27 struct e_error_trace
28 {
29 struct rec
30 {
31 char const * file;
32 int line;
33 friend std::ostream & operator<<( std::ostream & os, rec const & x )
34 {
35 return os << x.file << '(' << x.line << ')' << std::endl;
36 }
37 };
38
39 std::deque<rec> value;
40
41 friend std::ostream & operator<<( std::ostream & os, e_error_trace const & tr )
42 {
43 for( auto & i : tr.value )
44 os << i;
45 return os;
46 }
47 };
48
49 // The ERROR_TRACE macro is designed for use in functions that detect or forward errors
50 // up the call stack. If an error occurs, and if an error-handling scope provides a handler
51 // for e_error_trace, the supplied lambda is executed as the error bubbles up.
52 #define ERROR_TRACE auto _trace = leaf::on_error( []( e_error_trace & tr ) { tr.value.emplace_front(e_error_trace::rec{__FILE__, __LINE__}); } )
53
54 // Each function in the sequence below calls the previous function, and each function has
55 // failure_percent chance of failing. If a failure occurs, the ERROR_TRACE macro will cause
56 // the path the error takes to be captured in an e_error_trace.
57 int const failure_percent = 25;
58
59 leaf::result<void> f1()
60 {
61 ERROR_TRACE;
62 if( (std::rand()%100) > failure_percent )
63 return { };
64 else
65 return leaf::new_error();
66 }
67
68 leaf::result<void> f2()
69 {
70 ERROR_TRACE;
71 if( (std::rand()%100) > failure_percent )
72 return f1();
73 else
74 return leaf::new_error();
75 }
76
77 leaf::result<void> f3()
78 {
79 ERROR_TRACE;
80 if( (std::rand()%100) > failure_percent )
81 return f2();
82 else
83 return leaf::new_error();
84 }
85
86 leaf::result<void> f4()
87 {
88 ERROR_TRACE;
89 if( (std::rand()%100) > failure_percent )
90 return f3();
91 else
92 return leaf::new_error();
93 }
94
95 leaf::result<void> f5()
96 {
97 ERROR_TRACE;
98 if( (std::rand()%100) > failure_percent )
99 return f4();
100 else
101 return leaf::new_error();
102 }
103
104 int main()
105 {
106 for( int i=0; i!=10; ++i )
107 leaf::try_handle_all(
108 [&]() -> leaf::result<void>
109 {
110 std::cout << "Run # " << i << ": ";
111 BOOST_LEAF_CHECK(f5());
112 std::cout << "Success!" << std::endl;
113 return { };
114 },
115 #if ENABLE_ERROR_TRACE // This single #if enables or disables the capturing of the error trace.
116 []( e_error_trace const & tr )
117 {
118 std::cerr << "Error! Trace:" << std::endl << tr;
119 },
120 #endif
121 []
122 {
123 std::cerr << "Error!" << std::endl;
124 } );
125 return 0;
126 }
127
128 ////////////////////////////////////////
129
130 #ifdef BOOST_LEAF_NO_EXCEPTIONS
131
132 namespace boost
133 {
134 BOOST_LEAF_NORETURN void throw_exception( std::exception const & e )
135 {
136 std::cerr << "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e.what();
137 std::terminate();
138 }
139
140 struct source_location;
141 BOOST_LEAF_NORETURN void throw_exception( std::exception const & e, boost::source_location const & )
142 {
143 throw_exception(e);
144 }
145 }
146
147 #endif