]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/leaf/example/error_trace.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / leaf / example / error_trace.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// This program demonstrates the use of leaf::on_error to capture the path an
7// error takes as is bubbles up the call stack. The error path-capturing code
8// only runs if:
20effc67 9// - An error occurs, and
1e59de90
TL
10// - A handler that takes e_error_trace argument is present. Otherwise none of
11// the error trace machinery will be invoked by LEAF.
20effc67 12
1e59de90
TL
13// This example is similar to error_log, except the path the error takes is
14// recorded in a std::deque, rather than just printed in-place.
20effc67 15
1e59de90 16#include <boost/leaf.hpp>
20effc67
TL
17#include <iostream>
18#include <deque>
19#include <cstdlib>
20
21#define ENABLE_ERROR_TRACE 1
22
23namespace leaf = boost::leaf;
24
1e59de90
TL
25// The error trace is activated only if an error handling scope provides a
26// handler for e_error_trace.
20effc67
TL
27struct 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
1e59de90
TL
49// The ERROR_TRACE macro is designed for use in functions that detect or forward
50// errors up the call stack. If an error occurs, and if an error handling scope
51// provides a handler for e_error_trace, the supplied lambda is executed as the
52// error bubbles up.
20effc67
TL
53#define ERROR_TRACE auto _trace = leaf::on_error( []( e_error_trace & tr ) { tr.value.emplace_front(e_error_trace::rec{__FILE__, __LINE__}); } )
54
1e59de90
TL
55// Each function in the sequence below calls the previous function, and each
56// function has failure_percent chance of failing. If a failure occurs, the
57// ERROR_TRACE macro will cause the path the error takes to be captured in an
58// e_error_trace.
20effc67
TL
59int const failure_percent = 25;
60
61leaf::result<void> f1()
62{
63 ERROR_TRACE;
64 if( (std::rand()%100) > failure_percent )
65 return { };
66 else
67 return leaf::new_error();
68}
69
70leaf::result<void> f2()
71{
72 ERROR_TRACE;
73 if( (std::rand()%100) > failure_percent )
74 return f1();
75 else
76 return leaf::new_error();
77}
78
79leaf::result<void> f3()
80{
81 ERROR_TRACE;
82 if( (std::rand()%100) > failure_percent )
83 return f2();
84 else
85 return leaf::new_error();
86}
87
88leaf::result<void> f4()
89{
90 ERROR_TRACE;
91 if( (std::rand()%100) > failure_percent )
92 return f3();
93 else
94 return leaf::new_error();
95}
96
97leaf::result<void> f5()
98{
99 ERROR_TRACE;
100 if( (std::rand()%100) > failure_percent )
101 return f4();
102 else
103 return leaf::new_error();
104}
105
106int 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_TRACE // This single #if enables or disables the capturing of the error trace.
118 []( e_error_trace const & tr )
119 {
120 std::cerr << "Error! Trace:" << std::endl << tr;
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
134namespace 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