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
|
||||
#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.
|
||||
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||
|
|
@ -767,8 +779,10 @@ NAMESPACE_END
|
|||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||
#elif defined(__clang__)
|
||||
# if __has_feature(cxx_alignof)
|
||||
# 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)
|
||||
|
|
|
|||
|
|
@ -757,6 +757,18 @@ NAMESPACE_END
|
|||
# define CRYPTOPP_CXX11_ATOMICS 1
|
||||
#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.
|
||||
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
||||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||
|
|
@ -765,8 +777,10 @@ NAMESPACE_END
|
|||
# define CRYPTOPP_CXX11_ALIGNAS 1
|
||||
# define CRYPTOPP_CXX11_ALIGNOF 1
|
||||
#elif defined(__clang__)
|
||||
# if __has_feature(cxx_alignof)
|
||||
# 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)
|
||||
|
|
|
|||
37
misc.h
37
misc.h
|
|
@ -236,10 +236,12 @@ struct NewObject
|
|||
//! \tparam T the class or type
|
||||
//! \tparam F the object factory for T
|
||||
//! \tparam instance the initiali instance count
|
||||
//! \details This class safely initializes a static object in a multithreaded environment
|
||||
//! without using locks (for portability). Note that 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 is by design.
|
||||
//! \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
|
||||
//! 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>
|
||||
class Singleton
|
||||
{
|
||||
|
|
@ -256,28 +258,29 @@ 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)
|
||||
//! \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>
|
||||
const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
|
||||
{
|
||||
static volatile simple_ptr<T> s_pObject;
|
||||
T *p = s_pObject.m_p;
|
||||
static std::mutex s_mutex;
|
||||
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);
|
||||
|
||||
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;
|
||||
s_pObject.store(newObject, std::memory_order_relaxed);
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
|
||||
return *newObject;
|
||||
|
|
|
|||
Loading…
Reference in New Issue