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.
This commit is contained in:
Denis Blank 2019-11-16 17:13:23 +01:00
parent cacb84371a
commit 117a716de1

View File

@ -708,25 +708,34 @@ struct final_callback : util::non_copyable {
void operator()(Args... /*args*/) && { void operator()(Args... /*args*/) && {
} }
void operator()(exception_arg_t, exception_t error) && { void operator()(exception_arg_t, exception_t exception) && {
(void)error; // 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 #ifndef CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS
// There were unhandled errors inside the asynchronous call chain! // There were unhandled errors inside the asynchronous call chain!
// Define `CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS` in order // Define `CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS` in order
// to ignore unhandled errors!" // to ignore unhandled errors!"
#if defined(CONTINUABLE_HAS_EXCEPTIONS) #if defined(CONTINUABLE_HAS_EXCEPTIONS)
try { try {
std::rethrow_exception(error); std::rethrow_exception(exception);
} catch (std::exception const& exception) { } catch (std::exception const& unhandled) {
(void)exception; (void)unhandled;
CTI_DETAIL_TRAP(); CTI_DETAIL_TRAP();
} catch (...) { } catch (...) {
CTI_DETAIL_TRAP(); CTI_DETAIL_TRAP();
} }
#else #else
CTI_DETAIL_TRAP(); CTI_DETAIL_TRAP();
#endif #endif
#endif // CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS #endif // CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS
}
} }
void set_value(Args... args) noexcept { void set_value(Args... args) noexcept {