From 19358d1c420324d55400b9976d2912e77bdce702 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 5 Jul 2017 17:08:26 +0200 Subject: [PATCH] util/Exception: add more utility functions --- src/util/Exception.hxx | 64 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/util/Exception.hxx b/src/util/Exception.hxx index b79796fdc..e5797e7dd 100644 --- a/src/util/Exception.hxx +++ b/src/util/Exception.hxx @@ -30,9 +30,73 @@ #ifndef EXCEPTION_HXX #define EXCEPTION_HXX +#include "Compiler.h" + #include #include +/** + * Throws the specified exception. There is an overload for + * std::exception_ptr which throws the contained exception instead of + * the std::exception_ptr itself. + */ +template +gcc_noreturn +inline void +ThrowException(T &&t) +{ + throw t; +} + +gcc_noreturn +inline void +ThrowException(std::exception_ptr ep) +{ + std::rethrow_exception(ep); +} + +/** + * Create a nested exception, wrapping #ep inside (a copy of) #t. + */ +template +inline std::exception_ptr +NestException(std::exception_ptr ep, T &&t) noexcept +{ + try { + std::rethrow_exception(ep); + } catch (...) { + try { + std::throw_with_nested(std::forward(t)); + } catch (...) { + return std::current_exception(); + } + } +} + +/** + * Find an instance of #T in the nested exception chain, and rethrow + * it. Does nothing of no such instance was found. + */ +template +inline void +FindRetrowNested(std::exception_ptr ep) +{ + try { + std::rethrow_exception(ep); + } catch (const T &t) { + throw; + } catch (const std::exception &e) { + try { + std::rethrow_if_nested(e); + } catch (...) { + FindRetrowNested(std::current_exception()); + } + } catch (const std::nested_exception &ne) { + FindRetrowNested(ne.nested_ptr()); + } catch (...) { + } +} + /** * Obtain the full concatenated message of an exception and its nested * chain.