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 ***************