C++ boost::leaf examples
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

102 lines
2.6 KiB

// leaf_mutable_block.cpp
#include <boost/leaf.hpp>
#include <ctime>
#include <iostream>
#include <optional>
#include <string>
#include <utility>
namespace leaf = boost::leaf;
struct error_tag {};
struct open_error {};
struct write_error {};
struct diagnostic_context {
std::string file;
std::optional<std::string> user;
std::optional<int> privileges;
std::optional<int> chunk;
std::optional<std::size_t> chunk_size;
std::optional<std::time_t> timestamp;
};
leaf::result<void> write_chunk(int chunk, std::size_t size)
{
if (chunk == 3)
return leaf::new_error(write_error{});
return {};
}
leaf::result<void> process_file(std::string path, std::string user)
{
error_tag tag;
diagnostic_context diag;
diag.file = path;
diag.user = std::move(user);
diag.privileges = 0600;
[[maybe_unused]] auto tag_ctx = leaf::on_error(tag);
// on_error captures a snapshot of diag, not a reference, so any
// fields mutated later would be invisible unless re-registered.
[[maybe_unused]] auto diag_ctx = leaf::on_error(diag);
if (diag.file.empty())
return leaf::new_error(open_error{});
for (int i = 0; i != 5; ++i) {
diag.chunk = i;
diag.chunk_size = 4096;
diag.timestamp = std::time(nullptr);
// Re-registering publishes the updated snapshot; the newest
// registration wins for the handler.
[[maybe_unused]] auto refresh = leaf::on_error(diag);
auto r = write_chunk(i, 4096);
if (!r)
return r;
}
return {};
}
int main()
{
return leaf::try_handle_all(
[]() -> leaf::result<int> {
BOOST_LEAF_CHECK(process_file("data.bin", "alice"));
return 0;
},
[](error_tag const&, diagnostic_context const& d) {
// d is the newest snapshot taken before the error was raised,
// which is why chunk/chunk_size/timestamp are filled in here.
std::cerr << "operation failed: file=" << d.file;
if (d.user)
std::cerr << ", user=" << *d.user;
if (d.privileges)
std::cerr << ", privileges=" << *d.privileges;
if (d.chunk)
std::cerr << ", chunk=" << *d.chunk;
if (d.chunk_size)
std::cerr << ", chunk_size=" << *d.chunk_size;
if (d.timestamp)
std::cerr << ", time=" << *d.timestamp;
std::cerr << '\n';
return 1;
},
[] {
std::cerr << "operation failed before diagnostic context existed\n";
return 2;
}
);
}