Merge Atomics branch into Master

pull/186/head
Jeffrey Walton 2016-06-06 22:08:04 -04:00
parent 370483c7aa
commit e961c2da5b
4 changed files with 87 additions and 52 deletions

View File

@ -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)

View File

@ -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
View File

@ -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;

View File

@ -36,6 +36,10 @@ namespace std {
#include <atomic> #include <atomic>
#endif #endif
#if defined(CRYPTOPP_CXX11_SYNCHRONIZATION)
#include <mutex>
#endif
#include <cstdlib> #include <cstdlib>
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>