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