]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/leaf/examples/error_trace.cpp
1 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
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)
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.
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.
15 #include <boost/leaf/on_error.hpp>
16 #include <boost/leaf/handle_errors.hpp>
17 #include <boost/leaf/result.hpp>
22 #define ENABLE_ERROR_TRACE 1
24 namespace leaf
= boost::leaf
;
26 // The error trace is activated only if an error-handling scope provides a handler for e_error_trace.
33 friend std::ostream
& operator<<( std::ostream
& os
, rec
const & x
)
35 return os
<< x
.file
<< '(' << x
.line
<< ')' << std::endl
;
39 std::deque
<rec
> value
;
41 friend std::ostream
& operator<<( std::ostream
& os
, e_error_trace
const & tr
)
43 for( auto & i
: tr
.value
)
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__}); } )
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;
59 leaf::result
<void> f1()
62 if( (std::rand()%100) > failure_percent
)
65 return leaf::new_error();
68 leaf::result
<void> f2()
71 if( (std::rand()%100) > failure_percent
)
74 return leaf::new_error();
77 leaf::result
<void> f3()
80 if( (std::rand()%100) > failure_percent
)
83 return leaf::new_error();
86 leaf::result
<void> f4()
89 if( (std::rand()%100) > failure_percent
)
92 return leaf::new_error();
95 leaf::result
<void> f5()
98 if( (std::rand()%100) > failure_percent
)
101 return leaf::new_error();
106 for( int i
=0; i
!=10; ++i
)
107 leaf::try_handle_all(
108 [&]() -> leaf::result
<void>
110 std::cout
<< "Run # " << i
<< ": ";
111 BOOST_LEAF_CHECK(f5());
112 std::cout
<< "Success!" << std::endl
;
115 #if ENABLE_ERROR_TRACE // This single #if enables or disables the capturing of the error trace.
116 []( e_error_trace
const & tr
)
118 std::cerr
<< "Error! Trace:" << std::endl
<< tr
;
123 std::cerr
<< "Error!" << std::endl
;
128 ////////////////////////////////////////
130 #ifdef BOOST_LEAF_NO_EXCEPTIONS
134 BOOST_LEAF_NORETURN
void throw_exception( std::exception
const & e
)
136 std::cerr
<< "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e
.what();
140 struct source_location
;
141 BOOST_LEAF_NORETURN
void throw_exception( std::exception
const & e
, boost::source_location
const & )