]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/leaf/examples/capture_in_result.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 is a simple program that demonstrates the use of LEAF to transport error
7 // objects between threads, without using exception handling. See capture_eh.cpp
8 // for the version that uses exception handling.
10 #include <boost/leaf/capture.hpp>
11 #include <boost/leaf/handle_errors.hpp>
12 #include <boost/leaf/result.hpp>
20 namespace leaf
= boost::leaf
;
22 // Define several error types.
23 struct e_thread_id
{ std::thread::id value
; };
24 struct e_failure_info1
{ std::string value
; };
25 struct e_failure_info2
{ int value
; };
27 // A type that represents a successfully returned result from a task.
28 struct task_result
{ };
30 // This is our task function. It produces objects of type task_result, but it may fail...
31 leaf::result
<task_result
> task()
33 bool succeed
= (rand()%4) != 0; //...at random.
37 return leaf::new_error(
38 e_thread_id
{std::this_thread::get_id()},
39 e_failure_info1
{"info"},
40 e_failure_info2
{42} );
45 int const task_count
= 42;
47 // The error_handlers are used in this thread (see leaf::try_handle_all below). The
48 // arguments passed to individual lambdas are transported from the worker thread
49 // to the main thread automatically.
50 auto error_handlers
= std::make_tuple(
51 []( e_failure_info1
const & v1
, e_failure_info2
const & v2
, e_thread_id
const & tid
)
53 std::cerr
<< "Error in thread " << tid
.value
<< "! failure_info1: " << v1
.value
<< ", failure_info2: " << v2
.value
<< std::endl
;
55 []( leaf::diagnostic_info
const & unmatched
)
58 "Unknown failure detected" << std::endl
<<
59 "Cryptic diagnostic information follows" << std::endl
<<
63 // Container to collect the generated std::future objects.
64 std::vector
<std::future
<leaf::result
<task_result
>>> fut
;
66 // Launch the tasks, but rather than launching the task function directly, we launch a
67 // wrapper function which calls leaf::capture, passing a context object that will hold
68 // the error objects reported from the task in case of an error. The error types the
69 // context is able to hold statically are automatically deduced from the type of the
70 // error_handlers tuple.
71 std::generate_n( std::back_inserter(fut
), task_count
,
78 return leaf::capture(leaf::make_shared_context(error_handlers
), &task
);
82 // Wait on the futures, get the task results, handle errors.
88 [&]() -> leaf::result
<void>
90 BOOST_LEAF_AUTO(r
,f
.get());
92 // Success! Use r to access task_result.
93 std::cout
<< "Success!" << std::endl
;
94 (void) r
; // Presumably we'll somehow use the task_result.
101 ////////////////////////////////////////
103 #ifdef BOOST_LEAF_NO_EXCEPTIONS
107 BOOST_LEAF_NORETURN
void throw_exception( std::exception
const & e
)
109 std::cerr
<< "Terminating due to a C++ exception under BOOST_LEAF_NO_EXCEPTIONS: " << e
.what();
113 struct source_location
;
114 BOOST_LEAF_NORETURN
void throw_exception( std::exception
const & e
, boost::source_location
const & )