aboutsummaryrefslogtreecommitdiff
path: root/bpkg/utility
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-09-16 07:14:53 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-09-16 07:14:53 +0200
commitfbe0716682ad4fd64df670978785db372cbe2ed2 (patch)
treecc041c77ba1a95c42ae2f2d40298945a59d304bd /bpkg/utility
parent3ae0be3ad747b8ff63fa96091f4ea186d1bd9472 (diff)
Add exception_guard
Diffstat (limited to 'bpkg/utility')
-rw-r--r--bpkg/utility43
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