From 8bb9197adcb5b40edb10fa0359cc59f2cf9e9937 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Mon, 2 May 2016 23:38:10 -0400 Subject: [PATCH] Add atomics support --- config.h | 13 +++++++++++++ config.recommend | 13 +++++++++++++ misc.h | 32 +++++++++++++++++++++++++++++++- stdcpp.h | 4 ++++ 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/config.h b/config.h index 2e71bcb8..3d4673ea 100644 --- a/config.h +++ b/config.h @@ -664,6 +664,19 @@ NAMESPACE_END // C++11 or C++14 is available #if defined(CRYPTOPP_CXX11) +// 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/config.recommend b/config.recommend index ad845e88..66a69fd3 100644 --- a/config.recommend +++ b/config.recommend @@ -664,6 +664,19 @@ NAMESPACE_END // C++11 or C++14 is available #if defined(CRYPTOPP_CXX11) +// 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 d9f98cad..291b8dc1 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 *************** diff --git a/stdcpp.h b/stdcpp.h index 66efc203..22cee7a2 100644 --- a/stdcpp.h +++ b/stdcpp.h @@ -32,6 +32,10 @@ namespace std { #include #endif +#if defined(CRYPTOPP_CXX11_ATOMICS) +#include +#endif + #include #include #include