diff --git a/config.recommend b/config.recommend index a824ce1c..9a9b2b6e 100644 --- a/config.recommend +++ b/config.recommend @@ -763,6 +763,19 @@ NAMESPACE_END # define CRYPTOPP_CXX11_ATOMICS 1 #endif // atomics +// atomics: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.1/3.2; and Intel 13.0. +#if (CRYPTOPP_MSC_VERSION >= 1700) +# define CRYPTOPP_CXX11_ATOMICS 1 +#elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300) +# define CRYPTOPP_CXX11_ATOMICS 1 +#elif defined(__clang__) +# if __has_feature(cxx_atomic) +# define CRYPTOPP_CXX11_ATOMICS 1 +# endif +#elif (CRYPTOPP_GCC_VERSION >= 40400) +# define CRYPTOPP_CXX11_ATOMICS 1 +#endif // atomics + // alignof/alignas: MS at VS2013 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0. #if (CRYPTOPP_MSC_VERSION >= 1900) # define CRYPTOPP_CXX11_ALIGNAS 1 diff --git a/misc.h b/misc.h index 90c9f9a4..9e33688e 100644 --- a/misc.h +++ b/misc.h @@ -218,7 +218,9 @@ struct NewObject //! _ReadWriteBarrier() or __asm__("" ::: "memory"). #define MEMORY_BARRIER ... #else -#if (_MSC_VER >= 1400) +#if defined(CRYPTOPP_CXX11_ATOMICS) +# define MEMORY_BARRIER() std::atomic_thread_fence(std::memory_order_acq_rel) +#elif (_MSC_VER >= 1400) # pragma intrinsic(_ReadWriteBarrier) # define MEMORY_BARRIER() _ReadWriteBarrier() #elif defined(__INTEL_COMPILER) @@ -254,6 +256,33 @@ private: //! \brief Return a reference to the inner Singleton object //! \details Ref() is used to create the object using the object factory. The //! object is only created once with the limitations discussed in the class documentation. +#if defined(CRYPTOPP_CXX11_ATOMICS) +template + const T & Singleton::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const +{ + static volatile simple_ptr s_pObject; + T *p = s_pObject.m_p; + std::atomic_thread_fence(std::memory_order_acquire); + + if (p) + return *p; + + T *newObject = m_objectFactory(); + p = s_pObject.m_p; + std::atomic_thread_fence(std::memory_order_acquire); + + if (p) + { + delete newObject; + return *p; + } + + s_pObject.m_p = newObject; + std::atomic_thread_fence(std::memory_order_release); + + return *newObject; +} +#else template const T & Singleton::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const { @@ -279,6 +308,7 @@ const T & Singleton::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const return *newObject; } +#endif // ************** misc functions ***************