aboutsummaryrefslogtreecommitdiff
path: root/butl/utility
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-12-13 16:39:58 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-12-13 16:39:58 +0200
commita4199b808fd678f74935d540490eae9dc78a9ffe (patch)
tree16d1f0e583c926838b92722e000fae2c1ac4aa9e /butl/utility
parentb05e24a7f512c1f005dbcb67b3fce8b3d16e110e (diff)
Fix thread safety issue
Diffstat (limited to 'butl/utility')
-rw-r--r--butl/utility46
1 files changed, 36 insertions, 10 deletions
diff --git a/butl/utility b/butl/utility
index c57aabb..02d9331 100644
--- a/butl/utility
+++ b/butl/utility
@@ -9,10 +9,11 @@
#include <cstddef> // size_t
#include <utility> // move(), forward()
#include <cstring> // strcmp(), strlen()
-#include <exception> // uncaught_exception()
+#include <exception> // uncaught_exception(s)()
//#include <functional> // hash
#include <butl/export>
+#include <butl/config>
namespace butl
{
@@ -153,15 +154,6 @@ namespace butl
// 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.
- //
- LIBBUTL_EXPORT extern bool exception_unwinding_dtor;
-
template <typename F>
struct exception_guard;
@@ -172,6 +164,39 @@ namespace butl
return exception_guard<F> (std::move (f));
}
+#ifdef BUTL_CXX17_UNCAUGHT_EXCEPTIONS
+ template <typename F>
+ struct exception_guard
+ {
+ exception_guard (F f)
+ : f_ (std::move (f)),
+ u_ (std::uncaught_exceptions ()) {}
+
+ ~exception_guard ()
+ {
+ if (u_ != std::uncaught_exceptions ())
+ f_ ();
+ }
+
+ private:
+ F f_;
+ int u_;
+ };
+#else
+ // Fallback implementation using a TLS flag.
+ //
+ // True means we are in the body of a destructor that is being called as
+ // part of the exception stack unwindining.
+ //
+ LIBBUTL_EXPORT
+ extern
+#ifdef BUTL_CXX11_THREAD_LOCAL
+ thread_local
+#else
+ __thread
+#endif
+ bool exception_unwinding_dtor;
+
template <typename F>
struct exception_guard
{
@@ -189,6 +214,7 @@ namespace butl
private:
F f_;
};
+#endif
}
#include <butl/utility.ixx>