aboutsummaryrefslogtreecommitdiff
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
parent3ae0be3ad747b8ff63fa96091f4ea186d1bd9472 (diff)
Add exception_guard
-rw-r--r--bpkg/diagnostics.cxx4
-rw-r--r--bpkg/utility43
-rw-r--r--bpkg/utility.cxx2
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;
}