diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-09-16 07:14:53 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-09-16 07:14:53 +0200 |
commit | fbe0716682ad4fd64df670978785db372cbe2ed2 (patch) | |
tree | cc041c77ba1a95c42ae2f2d40298945a59d304bd | |
parent | 3ae0be3ad747b8ff63fa96091f4ea186d1bd9472 (diff) |
Add exception_guard
-rw-r--r-- | bpkg/diagnostics.cxx | 4 | ||||
-rw-r--r-- | bpkg/utility | 43 | ||||
-rw-r--r-- | bpkg/utility.cxx | 2 |
3 files changed, 48 insertions, 1 deletions
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 <iostream> +#include <bpkg/utility> + 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 <utility> // move() +#include <exception> // uncaught_exception () + #include <bpkg/types> 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 <typename F> + struct exception_guard; + + template <typename F> + inline exception_guard<F> + make_exception_guard (F f) + { + return exception_guard<F> (std::move (f)); + } + + template <typename F> + 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; } |