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