aboutsummaryrefslogtreecommitdiff
path: root/build/utility
diff options
context:
space:
mode:
Diffstat (limited to 'build/utility')
-rw-r--r--build/utility53
1 files changed, 52 insertions, 1 deletions
diff --git a/build/utility b/build/utility
index bcbf834..5523e8b 100644
--- a/build/utility
+++ b/build/utility
@@ -5,9 +5,12 @@
#ifndef BUILD_UTILITY
#define BUILD_UTILITY
+#include <tuple>
#include <string>
-#include <unordered_set>
+#include <utility>
#include <cstring> // strcmp
+#include <exception>
+#include <unordered_set>
namespace build
@@ -26,6 +29,54 @@ namespace build
bool operator() (const P& x, const P& y) const {return *x < *y;}
};
+ // Call a function if there is an exception.
+ //
+
+ // 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, typename T>
+ struct exception_guard;
+
+ template <typename F, typename... A>
+ inline exception_guard<F, std::tuple<A&&...>>
+ make_exception_guard (F f, A&&... a)
+ {
+ return exception_guard<F, std::tuple<A&&...>> (
+ std::move (f), std::forward_as_tuple (a...));
+ }
+
+ template <typename F, typename... A>
+ struct exception_guard<F, std::tuple<A...>>
+ {
+ typedef std::tuple<A...> T;
+
+ exception_guard (F f, T a): f_ (std::move (f)), a_ (std::move (a)) {}
+ ~exception_guard ()
+ {
+ if (std::uncaught_exception ())
+ {
+ exception_unwinding_dtor = true;
+ call (std::index_sequence_for<A...> ());
+ exception_unwinding_dtor = false;
+ }
+ }
+
+ private:
+ template <std::size_t... I>
+ void
+ call (std::index_sequence<I...>) {f_ (std::get<I> (a_)...);}
+
+ F f_;
+ T a_;
+ };
+
// Pools (@@ perhaps move into a separate header).
//
struct string_pool: std::unordered_set<std::string>