Use C++03 Singleton on select Microsoft platforms (Issues 372, 373, 389, 391)
We are back to the "... one object may end up being memory leaked" if faced with concurrent initializationpull/392/head
parent
354502d59d
commit
46c9cc725c
100
config.h
100
config.h
|
|
@ -787,113 +787,127 @@ 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; Intel 13.0; SunCC 12.5.
|
||||
// Compatibility with non-clang compilers.
|
||||
#ifndef __has_feature
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
// atomics: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.1/3.2; Intel 13.0; SunCC 5.14.
|
||||
#if (CRYPTOPP_MSC_VERSION >= 1700)
|
||||
# define CRYPTOPP_CXX11_ATOMICS 1
|
||||
#elif __has_feature(cxx_atomic)
|
||||
# define CRYPTOPP_CXX11_ATOMICS 1
|
||||
#elif (__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
|
||||
#elif (__SUNPRO_CC >= 0x5140)
|
||||
# define CRYPTOPP_CXX11_ATOMICS 1
|
||||
#endif // atomics
|
||||
|
||||
// synchronization: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.3; Xcode 5.0; Intel 12.0; SunCC 12.4.
|
||||
// synchronization: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.3; Xcode 5.0; Intel 12.0; SunCC 5.13.
|
||||
// TODO: verify Clang and Intel versions; find __has_feature(x) extension for Clang
|
||||
#if (CRYPTOPP_MSC_VERSION >= 1700)
|
||||
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||
#elif (__INTEL_COMPILER >= 1200)
|
||||
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||
#elif (CRYPTOPP_LLVM_CLANG_VERSION >= 30300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 50000)
|
||||
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||
#elif (__INTEL_COMPILER >= 1200)
|
||||
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||
#elif (CRYPTOPP_GCC_VERSION >= 40400)
|
||||
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||
#elif (__SUNPRO_CC >= 0x5130)
|
||||
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||
#endif // synchronization
|
||||
|
||||
// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.3; Intel 15.0; SunCC 12.4.
|
||||
// Dynamic Initialization and Destruction with Concurrency ("Magic Statics")
|
||||
// MS at VS2015 (19.00); GCC at 4.3; LLVM Clang at 2.9; Apple Clang at 4.0; Intel 11.1; SunCC 5.13.
|
||||
// Microsoft's implementation only works for Vista and above, so its further
|
||||
// limited. http://connect.microsoft.com/VisualStudio/feedback/details/1789709
|
||||
#if (CRYPTOPP_MSC_VERSION >= 1900) && ((WINVER >= 0x0600 /*_WIN32_WINNT_VISTA*/) || (_WIN32_WINNT >= 0x0600 /*_WIN32_WINNT_VISTA*/))
|
||||
# define CRYPTOPP_CXX11_DYNAMIC_INIT 1
|
||||
#elif (CRYPTOPP_LLVM_CLANG_VERSION >= 20900) || (CRYPTOPP_APPLE_CLANG_VERSION >= 40000)
|
||||
# define CRYPTOPP_CXX11_DYNAMIC_INIT 1
|
||||
#elif (__INTEL_COMPILER >= 1110)
|
||||
# define CRYPTOPP_CXX11_DYNAMIC_INIT 1
|
||||
#elif (CRYPTOPP_GCC_VERSION >= 40300)
|
||||
# define CRYPTOPP_CXX11_DYNAMIC_INIT 1
|
||||
#elif (__SUNPRO_CC >= 0x5130)
|
||||
# define CRYPTOPP_CXX11_DYNAMIC_INIT 1
|
||||
#endif // Dynamic Initialization compilers
|
||||
|
||||
// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.0; Intel 15.0; SunCC 5.13.
|
||||
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||
#elif __has_feature(cxx_alignas)
|
||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||
#elif (__INTEL_COMPILER >= 1500)
|
||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||
#elif defined(__clang__)
|
||||
# if __has_feature(cxx_alignas)
|
||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||
# endif
|
||||
# if __has_feature(cxx_alignof)
|
||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||
# endif
|
||||
#elif (CRYPTOPP_GCC_VERSION >= 40800)
|
||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||
#elif (__SUNPRO_CC >= 0x5130)
|
||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||
#endif // alignof/alignas
|
||||
#endif // alignas
|
||||
|
||||
// noexcept: MS at VS2015 (19.00); GCC at 4.6; Clang at 3.0; Intel 14.0; SunCC 12.4.
|
||||
// alignof: MS at VS2015 (19.00); GCC at 4.5; Clang at 2.9; Intel 15.0; SunCC 5.13.
|
||||
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||
#elif __has_feature(cxx_alignof)
|
||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||
#elif (__INTEL_COMPILER >= 1500)
|
||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||
#elif (CRYPTOPP_GCC_VERSION >= 40500)
|
||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||
#elif (__SUNPRO_CC >= 0x5130)
|
||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||
#endif // alignof
|
||||
|
||||
// noexcept: MS at VS2015 (19.00); GCC at 4.6; Clang at 3.0; Intel 14.0; SunCC 5.13.
|
||||
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
||||
# define CRYPTOPP_CXX11_NOEXCEPT 1
|
||||
#elif __has_feature(cxx_noexcept)
|
||||
# define CRYPTOPP_CXX11_NOEXCEPT 1
|
||||
#elif (__INTEL_COMPILER >= 1400)
|
||||
# define CRYPTOPP_CXX11_NOEXCEPT 1
|
||||
#elif defined(__clang__)
|
||||
# if __has_feature(cxx_noexcept)
|
||||
# define CRYPTOPP_CXX11_NOEXCEPT 1
|
||||
# endif
|
||||
#elif (CRYPTOPP_GCC_VERSION >= 40600)
|
||||
# define CRYPTOPP_CXX11_NOEXCEPT 1
|
||||
#elif (__SUNPRO_CC >= 0x5130)
|
||||
# define CRYPTOPP_CXX11_NOEXCEPT 1
|
||||
#endif // noexcept compilers
|
||||
|
||||
// variadic templates: MS at VS2013 (18.00); GCC at 4.3; Clang at 2.9; Intel 12.1; SunCC 12.4.
|
||||
// variadic templates: MS at VS2013 (18.00); GCC at 4.3; Clang at 2.9; Intel 12.1; SunCC 5.13.
|
||||
#if (CRYPTOPP_MSC_VERSION >= 1800)
|
||||
# define CRYPTOPP_CXX11_VARIADIC_TEMPLATES 1
|
||||
#elif __has_feature(cxx_variadic_templates)
|
||||
# define CRYPTOPP_CXX11_VARIADIC_TEMPLATES 1
|
||||
#elif (__INTEL_COMPILER >= 1210)
|
||||
# define CRYPTOPP_CXX11_VARIADIC_TEMPLATES 1
|
||||
#elif defined(__clang__)
|
||||
# if __has_feature(cxx_variadic_templates)
|
||||
# define CRYPTOPP_CXX11_VARIADIC_TEMPLATES 1
|
||||
# endif
|
||||
#elif (CRYPTOPP_GCC_VERSION >= 40300)
|
||||
# define CRYPTOPP_CXX11_VARIADIC_TEMPLATES 1
|
||||
#elif (__SUNPRO_CC >= 0x5130)
|
||||
# define CRYPTOPP_CXX11_VARIADIC_TEMPLATES 1
|
||||
#endif // variadic templates
|
||||
|
||||
// constexpr: MS at VS2015 (19.00); GCC at 4.6; Clang at 3.0; Intel 16.0; SunCC 12.4.
|
||||
// constexpr: MS at VS2015 (19.00); GCC at 4.6; Clang at 3.1; Intel 16.0; SunCC 5.13.
|
||||
// Intel has mis-supported the feature since at least ICPC 13.00
|
||||
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
||||
# define CRYPTOPP_CXX11_CONSTEXPR 1
|
||||
#elif __has_feature(cxx_constexpr)
|
||||
# define CRYPTOPP_CXX11_CONSTEXPR 1
|
||||
#elif (__INTEL_COMPILER >= 1600)
|
||||
# define CRYPTOPP_CXX11_CONSTEXPR 1
|
||||
#elif defined(__clang__)
|
||||
# if __has_feature(cxx_constexpr)
|
||||
# define CRYPTOPP_CXX11_CONSTEXPR 1
|
||||
# endif
|
||||
#elif (CRYPTOPP_GCC_VERSION >= 40600)
|
||||
# define CRYPTOPP_CXX11_CONSTEXPR 1
|
||||
#elif (__SUNPRO_CC >= 0x5130)
|
||||
# define CRYPTOPP_CXX11_CONSTEXPR 1
|
||||
#endif // constexpr compilers
|
||||
|
||||
// nullptr_t: MS at VS2010 (16.00); GCC at 4.6; Clang at 3.3; Intel 12.0; SunCC 12.4.
|
||||
// Intel has upported the feature since at least ICPC 12.00
|
||||
// nullptr_t: MS at VS2010 (16.00); GCC at 4.6; Clang at 3.3; Intel 10.0; SunCC 5.13.
|
||||
#if (CRYPTOPP_MSC_VERSION >= 1600)
|
||||
# define CRYPTOPP_CXX11_NULLPTR 1
|
||||
#elif (__INTEL_COMPILER >= 1200)
|
||||
#elif __has_feature(cxx_nullptr)
|
||||
# define CRYPTOPP_CXX11_NULLPTR 1
|
||||
#elif (__INTEL_COMPILER >= 1000)
|
||||
# define CRYPTOPP_CXX11_NULLPTR 1
|
||||
#elif defined(__clang__)
|
||||
# if __has_feature(cxx_nullptr)
|
||||
# define CRYPTOPP_CXX11_NULLPTR 1
|
||||
# endif
|
||||
#elif (CRYPTOPP_GCC_VERSION >= 40600)
|
||||
# define CRYPTOPP_CXX11_NULLPTR 1
|
||||
#elif (__SUNPRO_CC >= 0x5130)
|
||||
|
|
|
|||
22
misc.h
22
misc.h
|
|
@ -290,7 +290,7 @@ struct NewObject
|
|||
//! \brief Restricts the instantiation of a class to one static object without locks
|
||||
//! \tparam T the class or type
|
||||
//! \tparam F the object factory for T
|
||||
//! \tparam instance the initiali instance count
|
||||
//! \tparam instance an instance counter for the class object
|
||||
//! \details This class safely initializes a static object in a multithreaded environment. For C++03
|
||||
//! and below it will do so without using locks for portability. If two threads call Ref() at the same
|
||||
//! time, they may get back different references, and one object may end up being memory leaked. This
|
||||
|
|
@ -298,8 +298,14 @@ struct NewObject
|
|||
//! local storage on early Windows platforms, like Windows XP and Windows 2003.
|
||||
//! \details For C++11 and above, a standard double-checked locking pattern with thread fences
|
||||
//! are used. The locks and fences are standard and do not hinder portability.
|
||||
//! \sa <A HREF="http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/">Double-Checked
|
||||
//! Locking is Fixed In C++11</A>
|
||||
//! \details Microsoft's C++11 implementation provides the necessary primitive support on Windows Vista and
|
||||
//! above when using Visual Studio 2015 (<tt>cl.exe</tt> version 19.00). If C++11 is desired, you should
|
||||
//! set <tt>WINVER</tt> or <tt>_WIN32_WINNT</tt> to 0x600 (or above), and compile with Visual Studio 2015.
|
||||
//! \sa <A HREF="http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/">Double-Checked Locking
|
||||
//! is Fixed In C++11</A>, <A HREF="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm">Dynamic
|
||||
//! Initialization and Destruction with Concurrency</A> and
|
||||
//! <A HREF="http://msdn.microsoft.com/en-us/library/6yh4a9k1.aspx">Thread Local Storage (TLS)</A> on MSDN.
|
||||
//! \since Crypto++ 5.2
|
||||
template <class T, class F = NewObject<T>, int instance=0>
|
||||
class Singleton
|
||||
{
|
||||
|
|
@ -316,13 +322,15 @@ private:
|
|||
//! \brief Return a reference to the inner Singleton object
|
||||
//! \tparam T the class or type
|
||||
//! \tparam F the object factory for T
|
||||
//! \tparam instance an instance counter for the class 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.
|
||||
//! \sa <A HREF="http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/">Double-Checked Locking is Fixed In C++11</A>
|
||||
#if defined(CRYPTOPP_CXX11_ATOMICS) && defined(CRYPTOPP_CXX11_SYNCHRONIZATION)
|
||||
//! \since Crypto++ 5.2
|
||||
template <class T, class F, int instance>
|
||||
const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
|
||||
{
|
||||
#if defined(CRYPTOPP_CXX11_ATOMICS) && defined(CRYPTOPP_CXX11_SYNCHRONIZATION) && defined(CRYPTOPP_CXX11_DYNAMIC_INIT)
|
||||
static std::mutex s_mutex;
|
||||
static std::atomic<T*> s_pObject;
|
||||
|
||||
|
|
@ -344,11 +352,7 @@ template <class T, class F, int instance>
|
|||
std::atomic_thread_fence(std::memory_order_release);
|
||||
|
||||
return *newObject;
|
||||
}
|
||||
#else
|
||||
template <class T, class F, int instance>
|
||||
const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
|
||||
{
|
||||
static volatile simple_ptr<T> s_pObject;
|
||||
T *p = s_pObject.m_p;
|
||||
MEMORY_BARRIER();
|
||||
|
|
@ -370,8 +374,8 @@ const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
|
|||
MEMORY_BARRIER();
|
||||
|
||||
return *newObject;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// ************** misc functions ***************
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ ThreadLocalStorage::Err::Err(const std::string& operation, int error)
|
|||
{
|
||||
}
|
||||
|
||||
// Windows: "a process may have up to TLS_MINIMUM_AVAILABLE indexes (guaranteed to be greater than
|
||||
// or equal to 64)", https://support.microsoft.com/en-us/help/94804/info-thread-local-storage-overview
|
||||
ThreadLocalStorage::ThreadLocalStorage()
|
||||
{
|
||||
#ifdef HAS_WINTHREADS
|
||||
|
|
|
|||
Loading…
Reference in New Issue