From 71e08c702b0497b350830febdbfee05e2445ea9d Mon Sep 17 00:00:00 2001 From: Rasmus Munk Larsen Date: Sat, 12 Sep 2020 01:23:29 +0000 Subject: Make blueNorm threadsafe if C++11 atomics are available. --- Eigen/src/Core/StableNorm.h | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'Eigen/src/Core/StableNorm.h') diff --git a/Eigen/src/Core/StableNorm.h b/Eigen/src/Core/StableNorm.h index 77ea3c261..8000f9d33 100644 --- a/Eigen/src/Core/StableNorm.h +++ b/Eigen/src/Core/StableNorm.h @@ -10,6 +10,10 @@ #ifndef EIGEN_STABLENORM_H #define EIGEN_STABLENORM_H +#if EIGEN_HAS_CXX11_ATOMIC +#include +#endif + namespace Eigen { namespace internal { @@ -124,10 +128,29 @@ blueNorm_impl(const EigenBase& _vec) using std::sqrt; using std::abs; const Derived& vec(_vec.derived()); - static bool initialized = false; + +#if EIGEN_HAS_CXX11_ATOMIC + enum { + kNotInitialized = 0, + kInitializing = 1, + kInitialized = 2 + }; + static std::atomic initialized{kNotInitialized}; +#else + // Note: This is not theadsafe without C++11. + const bool kNotInitialized = false; + const bool kInitialized = true; + static bool initialized = kNotInitialized; +#endif static RealScalar b1, b2, s1m, s2m, rbig, relerr; - if(!initialized) + + while (initialized != kInitialized) { +#if EIGEN_HAS_CXX11_ATOMIC + // Checking again to see if another thread has already initialized the constants. + uint8_t val = kNotInitialized; + if (initialized.compare_exchange_strong(val, kInitializing) && val != kInitialized) { +#endif int ibeta, it, iemin, iemax, iexp; RealScalar eps; // This program calculates the machine-dependent constants @@ -156,7 +179,10 @@ blueNorm_impl(const EigenBase& _vec) eps = RealScalar(pow(double(ibeta), 1-it)); relerr = sqrt(eps); // tolerance for neglecting asml - initialized = true; + initialized = kInitialized; +#if EIGEN_HAS_CXX11_ATOMIC + } +#endif } Index n = vec.size(); RealScalar ab2 = b2 / RealScalar(n); -- cgit v1.2.3