Merge Atomics branch into Master
parent
370483c7aa
commit
e961c2da5b
16
config.h
16
config.h
|
|
@ -759,6 +759,18 @@ NAMESPACE_END
|
||||||
# define CRYPTOPP_CXX11_ATOMICS 1
|
# define CRYPTOPP_CXX11_ATOMICS 1
|
||||||
#endif // atomics
|
#endif // atomics
|
||||||
|
|
||||||
|
// synchronization: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.3; Xcode 5.0; and Intel 12.0.
|
||||||
|
// TODO: verify Clang and Intel versions; find __has_feature(x) extension for Clang
|
||||||
|
#if (CRYPTOPP_MSC_VERSION >= 1700)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1200)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#elif (CRYPTOPP_CLANG_VERSION >= 30300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 50000)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#elif (CRYPTOPP_GCC_VERSION >= 40400)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#endif // synchronization
|
||||||
|
|
||||||
// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0.
|
// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0.
|
||||||
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
||||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||||
|
|
@ -767,8 +779,10 @@ NAMESPACE_END
|
||||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||||
#elif defined(__clang__)
|
#elif defined(__clang__)
|
||||||
# if __has_feature(cxx_alignof)
|
# if __has_feature(cxx_alignas)
|
||||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||||
|
# endif
|
||||||
|
# if __has_feature(cxx_alignof)
|
||||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||||
# endif
|
# endif
|
||||||
#elif (CRYPTOPP_GCC_VERSION >= 40800)
|
#elif (CRYPTOPP_GCC_VERSION >= 40800)
|
||||||
|
|
|
||||||
|
|
@ -757,6 +757,18 @@ NAMESPACE_END
|
||||||
# define CRYPTOPP_CXX11_ATOMICS 1
|
# define CRYPTOPP_CXX11_ATOMICS 1
|
||||||
#endif // atomics
|
#endif // atomics
|
||||||
|
|
||||||
|
// synchronization: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.3; Xcode 5.0; and Intel 12.0.
|
||||||
|
// TODO: verify Clang and Intel versions; find __has_feature(x) extension for Clang
|
||||||
|
#if (CRYPTOPP_MSC_VERSION >= 1700)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1200)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#elif (CRYPTOPP_CLANG_VERSION >= 30300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 50000)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#elif (CRYPTOPP_GCC_VERSION >= 40400)
|
||||||
|
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
|
||||||
|
#endif // synchronization
|
||||||
|
|
||||||
// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0.
|
// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0.
|
||||||
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
||||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||||
|
|
@ -765,8 +777,10 @@ NAMESPACE_END
|
||||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||||
#elif defined(__clang__)
|
#elif defined(__clang__)
|
||||||
# if __has_feature(cxx_alignof)
|
# if __has_feature(cxx_alignas)
|
||||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||||
|
# endif
|
||||||
|
# if __has_feature(cxx_alignof)
|
||||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||||
# endif
|
# endif
|
||||||
#elif (CRYPTOPP_GCC_VERSION >= 40800)
|
#elif (CRYPTOPP_GCC_VERSION >= 40800)
|
||||||
|
|
|
||||||
37
misc.h
37
misc.h
|
|
@ -236,10 +236,12 @@ struct NewObject
|
||||||
//! \tparam T the class or type
|
//! \tparam T the class or type
|
||||||
//! \tparam F the object factory for T
|
//! \tparam F the object factory for T
|
||||||
//! \tparam instance the initiali instance count
|
//! \tparam instance the initiali instance count
|
||||||
//! \details This class safely initializes a static object in a multithreaded environment
|
//! \details This class safely initializes a static object in a multithreaded environment. For C++03
|
||||||
//! without using locks (for portability). Note that if two threads call Ref() at the same
|
//! 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
|
//! time, they may get back different references, and one object may end up being memory leaked. This
|
||||||
//! leaked. This is by design.
|
//! is by design. For C++11 and above, a standard double-checked locking pattern with memory fences
|
||||||
|
//! is 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>
|
||||||
template <class T, class F = NewObject<T>, int instance=0>
|
template <class T, class F = NewObject<T>, int instance=0>
|
||||||
class Singleton
|
class Singleton
|
||||||
{
|
{
|
||||||
|
|
@ -256,28 +258,29 @@ private:
|
||||||
//! \brief Return a reference to the inner Singleton object
|
//! \brief Return a reference to the inner Singleton object
|
||||||
//! \details Ref() is used to create the object using the object factory. The
|
//! \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.
|
//! object is only created once with the limitations discussed in the class documentation.
|
||||||
#if defined(CRYPTOPP_CXX11_ATOMICS)
|
//! \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)
|
||||||
template <class T, class F, int instance>
|
template <class T, class F, int instance>
|
||||||
const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
|
const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
|
||||||
{
|
{
|
||||||
static volatile simple_ptr<T> s_pObject;
|
static std::mutex s_mutex;
|
||||||
T *p = s_pObject.m_p;
|
static std::atomic<T*> s_pObject;
|
||||||
|
|
||||||
|
T *p = s_pObject.load(std::memory_order_relaxed);
|
||||||
|
std::atomic_thread_fence(std::memory_order_acquire);
|
||||||
|
|
||||||
|
if (p)
|
||||||
|
return *p;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(s_mutex);
|
||||||
|
p = s_pObject.load(std::memory_order_relaxed);
|
||||||
std::atomic_thread_fence(std::memory_order_acquire);
|
std::atomic_thread_fence(std::memory_order_acquire);
|
||||||
|
|
||||||
if (p)
|
if (p)
|
||||||
return *p;
|
return *p;
|
||||||
|
|
||||||
T *newObject = m_objectFactory();
|
T *newObject = m_objectFactory();
|
||||||
p = s_pObject.m_p;
|
s_pObject.store(newObject, std::memory_order_relaxed);
|
||||||
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);
|
std::atomic_thread_fence(std::memory_order_release);
|
||||||
|
|
||||||
return *newObject;
|
return *newObject;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue