From fbe0716682ad4fd64df670978785db372cbe2ed2 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 16 Sep 2015 07:14:53 +0200 Subject: Add exception_guard --- bpkg/diagnostics.cxx | 4 +++- bpkg/utility | 43 +++++++++++++++++++++++++++++++++++++++++++ bpkg/utility.cxx | 2 ++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/bpkg/diagnostics.cxx b/bpkg/diagnostics.cxx index 39ad1d2..697bd28 100644 --- a/bpkg/diagnostics.cxx +++ b/bpkg/diagnostics.cxx @@ -6,6 +6,8 @@ #include +#include + using namespace std; namespace bpkg @@ -62,7 +64,7 @@ namespace bpkg // this ugly special check which we will be able to get rid of // once C++17 uncaught_exceptions() becomes available. // - if (!empty_ && (!uncaught_exception () /*|| exception_unwinding_dtor*/)) + if (!empty_ && (!uncaught_exception () || exception_unwinding_dtor)) { *diag_stream << os_.str () << endl; diff --git a/bpkg/utility b/bpkg/utility index a5bafec..ea7dfa6 100644 --- a/bpkg/utility +++ b/bpkg/utility @@ -5,6 +5,9 @@ #ifndef BPKG_UTILITY #define BPKG_UTILITY +#include // move() +#include // uncaught_exception () + #include namespace bpkg @@ -39,6 +42,46 @@ namespace bpkg inline void run (const cstrings& args) {run (args.data ());} + + // Call a function if there is an exception. + // + + // True means we are in the body of a destructor that is being + // called as part of the exception stack unwindining. Used to + // compensate for the deficiencies of uncaught_exception() until + // C++17 uncaught_exceptions() becomes available. + // + // @@ MT: will have to be TLS. + // + extern bool exception_unwinding_dtor; + + template + struct exception_guard; + + template + inline exception_guard + make_exception_guard (F f) + { + return exception_guard (std::move (f)); + } + + template + struct exception_guard + { + exception_guard (F f): f_ (std::move (f)) {} + ~exception_guard () + { + if (std::uncaught_exception ()) + { + exception_unwinding_dtor = true; + f_ (); + exception_unwinding_dtor = false; + } + } + + private: + F f_; + }; } #endif // BPKG_UTILITY diff --git a/bpkg/utility.cxx b/bpkg/utility.cxx index f1e9a5a..632791c 100644 --- a/bpkg/utility.cxx +++ b/bpkg/utility.cxx @@ -132,4 +132,6 @@ namespace bpkg throw failed (); } } + + bool exception_unwinding_dtor = false; } -- cgit v1.1