From 117a716de16552ff239f8a5dbff91f5d3cc34249 Mon Sep 17 00:00:00 2001 From: Denis Blank Date: Sat, 16 Nov 2019 17:13:23 +0100 Subject: [PATCH] Test the class which represents exception_t against true before running unhandled exception handlers. * This allows cheap cancellation of the control flow by passing a default constructed `exception_t` object to `set_exception`. * Since possible representatives like - `std::exception_ptr` - `std::error_code` - `std::error_condition` can be default constructed we have to test them anyway before possibly rethrowing them. --- include/continuable/detail/core/base.hpp | 37 +++++++++++++++--------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/include/continuable/detail/core/base.hpp b/include/continuable/detail/core/base.hpp index e41c1d0..20a3720 100644 --- a/include/continuable/detail/core/base.hpp +++ b/include/continuable/detail/core/base.hpp @@ -708,25 +708,34 @@ struct final_callback : util::non_copyable { void operator()(Args... /*args*/) && { } - void operator()(exception_arg_t, exception_t error) && { - (void)error; + void operator()(exception_arg_t, exception_t exception) && { + // Only handle the exception when it is present, otherwise handle it as + // a cancellation of the control flow. + // This behaviour is intentionally correct for + // - `std::exception_ptr` + // - `std::error_code` + // - `std::error_condition` + // which allow to be default constructed and then return false + // by their corresponding `operator bool()`. + if (bool(exception)) { #ifndef CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS - // There were unhandled errors inside the asynchronous call chain! - // Define `CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS` in order - // to ignore unhandled errors!" + // There were unhandled errors inside the asynchronous call chain! + // Define `CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS` in order + // to ignore unhandled errors!" #if defined(CONTINUABLE_HAS_EXCEPTIONS) - try { - std::rethrow_exception(error); - } catch (std::exception const& exception) { - (void)exception; - CTI_DETAIL_TRAP(); - } catch (...) { - CTI_DETAIL_TRAP(); - } + try { + std::rethrow_exception(exception); + } catch (std::exception const& unhandled) { + (void)unhandled; + CTI_DETAIL_TRAP(); + } catch (...) { + CTI_DETAIL_TRAP(); + } #else - CTI_DETAIL_TRAP(); + CTI_DETAIL_TRAP(); #endif #endif // CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS + } } void set_value(Args... args) noexcept {