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