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

View File

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

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

View File

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