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 /bpkg/utility | |
parent | 3ae0be3ad747b8ff63fa96091f4ea186d1bd9472 (diff) |
Add exception_guard
Diffstat (limited to 'bpkg/utility')
-rw-r--r-- | bpkg/utility | 43 |
1 files changed, 43 insertions, 0 deletions
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 |