From dca575992b34611d20f50c5db47e4b533cd7dc69 Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Fri, 13 Sep 2019 01:02:56 +0200 Subject: [PATCH] crimson: introduce syntactic sugar for visiting errorator. Signed-off-by: Radoslaw Zarzynski --- src/crimson/common/errorator.h | 54 ++++++++++++++++++++++++++++++++++ src/crimson/osd/pg_backend.cc | 36 ++++++++++------------- 2 files changed, 69 insertions(+), 21 deletions(-) diff --git a/src/crimson/common/errorator.h b/src/crimson/common/errorator.h index 2820f25ca77..faa714afc94 100644 --- a/src/crimson/common/errorator.h +++ b/src/crimson/common/errorator.h @@ -31,6 +31,15 @@ struct unthrowable_wrapper { return instance; } + template + static auto handle(Func&& func) { + return [ + func = std::forward(func) + ] (const unthrowable_wrapper&) mutable -> decltype(auto) { + return std::invoke(std::forward(func)); + }; + } + private: // can be used only to initialize the `instance` member explicit unthrowable_wrapper() = default; @@ -99,6 +108,34 @@ public: } }; +namespace _impl { + template struct always_false : std::false_type {}; +}; + +template +static constexpr auto composer(FuncHead&& head, FuncTail&&... tail) { + return [ + head = std::forward(head), + // perfect forwarding in lambda's closure isn't availble in C++17 + // using tuple as workaround; see: https://stackoverflow.com/a/49902823 + tail = std::make_tuple(std::forward(tail)...) + ] (auto&&... args) mutable -> decltype(auto) { + if constexpr (std::is_invocable_v) { + return std::invoke(std::forward(head), + std::forward(args)...); + } else if constexpr (sizeof...(FuncTail) > 0) { + using next_composer_t = decltype(composer); + auto&& next = std::apply(composer, + std::move(tail)); + return std::invoke(std::move(next), + std::forward(args)...); + } else { + static_assert( + _impl::always_false::value, "composition is not exhaustive"); + } + }; +} + template struct errorator { template > @@ -270,6 +307,23 @@ struct errorator { })}; } + // taking ErrorFuncOne and ErrorFuncTwo separately from ErrorFuncTail + // to avoid SFINAE + template + auto safe_then(ValueFunc&& value_func, + ErrorFuncOne&& error_func_one, + ErrorFuncTwo&& error_func_two, + ErrorFuncTail&&... error_func_tail) { + return safe_then( + std::forward(value_func), + composer(std::forward(error_func_one), + std::forward(error_func_two), + std::forward(error_func_tail)...)); + } + template void then(Func&&) = delete; diff --git a/src/crimson/osd/pg_backend.cc b/src/crimson/osd/pg_backend.cc index b20c2ae3c4d..dec2fb84b60 100644 --- a/src/crimson/osd/pg_backend.cc +++ b/src/crimson/osd/pg_backend.cc @@ -125,17 +125,16 @@ PGBackend::_load_os(const hobject_t& oid) os_cache.insert(oid, std::make_unique(object_info_t{bl}, true /* exists */))); }, - [oid, this] (const auto& e) { - using T = std::decay_t; - if constexpr (std::is_same_v || - std::is_same_v) { - return seastar::make_ready_future( - os_cache.insert(oid, - std::make_unique(object_info_t{oid}, false))); - } else { - static_assert(always_false::value, "non-exhaustive visitor!"); - } - }); + crimson::ct_error::enoent::handle([oid, this] { + return seastar::make_ready_future( + os_cache.insert(oid, + std::make_unique(object_info_t{oid}, false))); + }), + crimson::ct_error::enodata::handle([oid, this] { + return seastar::make_ready_future( + os_cache.insert(oid, + std::make_unique(object_info_t{oid}, false))); + })); } seastar::future @@ -493,16 +492,11 @@ seastar::future<> PGBackend::getxattr( osd_op.op.xattr.value_len = osd_op.outdata.length(); return seastar::now(); //ctx->delta_stats.num_rd_kb += shift_round_up(osd_op.outdata.length(), 10); - }, [] (const auto& e) { - using T = std::decay_t; - if constexpr (std::is_same_v) { - return seastar::make_exception_future<>(crimson::osd::object_not_found{}); - } else if constexpr (std::is_same_v) { - return seastar::make_exception_future<>(crimson::osd::no_message_available{}); - } else { - static_assert(always_false::value, "non-exhaustive visitor!"); - } - }); + }, crimson::ct_error::enoent::handle([] { + return seastar::make_exception_future<>(crimson::osd::object_not_found{}); + }), crimson::ct_error::enodata::handle([] { + return seastar::make_exception_future<>(crimson::osd::no_message_available{}); + })); //ctx->delta_stats.num_rd++; } -- 2.39.5