-//$$CDS-header$$
-
-#ifndef __CDS_COMPILER_CXX11_ATOMIC_H
-#define __CDS_COMPILER_CXX11_ATOMIC_H
+/*
+ This file is a part of libcds - Concurrent Data Structures library
+
+ (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+ Source code repo: http://github.com/khizmax/libcds/
+ Download: http://sourceforge.net/projects/libcds/files/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef CDSLIB_COMPILER_CXX11_ATOMIC_H
+#define CDSLIB_COMPILER_CXX11_ATOMIC_H
//@cond
+#include <type_traits> // make_unsigned
#include <cds/details/defs.h>
#include <cds/details/aligned_type.h>
-namespace cds { namespace cxx11_atomics {
+namespace cds { namespace cxx11_atomic {
typedef enum memory_order {
memory_order_relaxed,
memory_order_consume,
memory_order_seq_cst
} memory_order;
-}} // namespace cds::cxx11_atomics
+}} // namespace cds::cxx11_atomic
#if CDS_COMPILER == CDS_COMPILER_MSVC || (CDS_COMPILER == CDS_COMPILER_INTEL && CDS_OS_INTERFACE == CDS_OSI_WINDOWS)
# error "Undefined compiler"
#endif
-// In C++11, make_unsigned is declared in <type_traits>
-#include <boost/type_traits/make_unsigned.hpp> // for make_unsigned
-
-namespace cds { namespace cxx11_atomics {
+namespace cds { namespace cxx11_atomic {
// forward declarations
template <class T>
template <>
struct primary_type<1>
{
- typedef cds::uint8_t type;
+ typedef std::uint8_t type;
};
template <>
struct primary_type<2>
{
- typedef cds::uint16_t type;
+ typedef std::uint16_t type;
};
template <>
struct primary_type<4>
{
- typedef cds::uint32_t type;
+ typedef std::uint32_t type;
};
template <>
struct primary_type<8>
{
- typedef cds::uint64_t type;
+ typedef std::uint64_t type;
};
template <typename T, typename Primary>
struct atomic_integral_bitwise_ops
{
public:
- typedef typename boost::make_unsigned<T>::type unsigned_type;
+ typedef typename std::make_unsigned<T>::type unsigned_type;
typedef atomic_generic_ops<unsigned_type, sizeof(unsigned_type)> atomic_ops;
static T fetch_and(T volatile * pDest, T val, memory_order order) CDS_NOEXCEPT
// cas
static bool atomic_compare_exchange_weak_explicit( T volatile * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas8_weak( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_weak_explicit( T * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas8_weak( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_weak( T volatile * pDest, T * expected, T desired ) CDS_NOEXCEPT
}
static bool atomic_compare_exchange_strong_explicit( T volatile * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas8_strong( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_strong_explicit( T * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas8_strong( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_strong( T volatile * pDest, T * expected, T desired ) CDS_NOEXCEPT
// cas
static bool atomic_compare_exchange_weak_explicit( T volatile * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas16_weak( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_weak_explicit( T * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas16_weak( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_weak( T volatile * pDest, T * expected, T desired ) CDS_NOEXCEPT
}
static bool atomic_compare_exchange_strong_explicit( T volatile * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas16_strong( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_strong_explicit( T * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas16_strong( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_strong( T volatile * pDest, T * expected, T desired ) CDS_NOEXCEPT
// cas
static bool atomic_compare_exchange_weak_explicit( T volatile * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas32_weak( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_weak_explicit( T * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas32_weak( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_weak( T volatile * pDest, T * expected, T desired ) CDS_NOEXCEPT
}
static bool atomic_compare_exchange_strong_explicit( T volatile * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas32_strong( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_strong_explicit( T * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas32_strong( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_strong( T volatile * pDest, T * expected, T desired ) CDS_NOEXCEPT
// cas
static bool atomic_compare_exchange_weak_explicit( T volatile * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas64_weak( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_weak_explicit( T * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas64_weak( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_weak( T volatile * pDest, T * expected, T desired ) CDS_NOEXCEPT
}
static bool atomic_compare_exchange_strong_explicit( T volatile * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas64_strong( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_strong_explicit( T * pDest, T * expected, T desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas64_strong( primary::ptr(pDest), primary::ref(*expected), primary::val(desired), mo_success, mo_fail );
}
static bool atomic_compare_exchange_strong( T volatile * pDest, T * expected, T desired ) CDS_NOEXCEPT
// cas
static bool atomic_compare_exchange_weak_explicit( T * volatile * pDest, T * * expected, T * desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas_ptr_weak( pDest, *expected, desired, mo_success, mo_fail );
}
static bool atomic_compare_exchange_weak_explicit( T * * pDest, T * * expected, T * desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas_ptr_weak( pDest, *expected, desired, mo_success, mo_fail );
}
static bool atomic_compare_exchange_weak( T * volatile * pDest, T ** expected, T * desired ) CDS_NOEXCEPT
}
static bool atomic_compare_exchange_strong_explicit( T * volatile * pDest, T ** expected, T * desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas_ptr_strong( pDest, *expected, desired, mo_success, mo_fail );
}
static bool atomic_compare_exchange_strong_explicit( T ** pDest, T ** expected, T * desired, memory_order mo_success, memory_order mo_fail ) CDS_NOEXCEPT
{
- assert( expected != NULL );
+ assert( expected );
return platform::cas_ptr_strong( pDest, *expected, desired, mo_success, mo_fail );
}
static bool atomic_compare_exchange_strong( T * volatile * pDest, T ** expected, T * desired ) CDS_NOEXCEPT
}
};
-#ifndef CDS_CXX11_DELETE_DEFINITION_SUPPORT
- class atomic_noncopyable
- {
- private:
- atomic_noncopyable(const atomic_noncopyable&);
- atomic_noncopyable& operator=(const atomic_noncopyable&);
- //atomic_noncopyable& operator=(const atomic_noncopyable&) volatile;
- protected:
-# ifdef CDS_CXX11_EXPLICITLY_DEFAULTED_FUNCTION_SUPPORT
- atomic_noncopyable() = default;
-# else
- atomic_noncopyable()
- {}
-# endif
- };
-#endif
-
template <typename T>
struct atomic_integral
-#ifndef CDS_CXX11_DELETE_DEFINITION_SUPPORT
- : atomic_noncopyable
-#endif
{
private:
typename cds::details::aligned_type<T, sizeof(T)>::type volatile m_val;
return atomic_ops::atomic_fetch_xor_explicit( &m_val, val, order );
}
-#ifdef CDS_CXX11_EXPLICITLY_DEFAULTED_FUNCTION_SUPPORT
atomic_integral() = default;
-#else
- atomic_integral() CDS_NOEXCEPT
- {}
-#endif
CDS_CONSTEXPR atomic_integral(T val) CDS_NOEXCEPT
: m_val(val)
{}
-#ifdef CDS_CXX11_DELETE_DEFINITION_SUPPORT
atomic_integral(const atomic_integral&) = delete;
atomic_integral& operator=(const atomic_integral&) = delete;
atomic_integral& operator=(const atomic_integral&) volatile = delete;
-#endif
+
T operator=(T val) volatile CDS_NOEXCEPT
{
store(val);
template <class T>
struct atomic
-#ifndef CDS_CXX11_DELETE_DEFINITION_SUPPORT
- : details::atomic_noncopyable
-#endif
{
private:
typedef details::atomic_generic_ops<T, sizeof(T), typename details::select_primary_type<T>::type > atomic_ops;
return compare_exchange_strong( expected, desired, success_order, memory_order_relaxed );
}
-#ifdef CDS_CXX11_EXPLICITLY_DEFAULTED_FUNCTION_SUPPORT
atomic() = default;
-#else
- atomic()
- {}
-#endif
CDS_CONSTEXPR atomic(T val)
: m_data( val )
{}
-#ifdef CDS_CXX11_DELETE_DEFINITION_SUPPORT
atomic(const atomic&) = delete;
atomic& operator=(const atomic&) = delete;
atomic& operator=(const atomic&) volatile = delete;
-#endif
T operator=(T val) volatile CDS_NOEXCEPT
{
}
};
-#if defined(CDS_CXX11_EXPLICITLY_DEFAULTED_FUNCTION_SUPPORT) && defined(CDS_CXX11_DELETE_DEFINITION_SUPPORT)
# define CDS_DECLARE_ATOMIC_INTEGRAL( _type ) \
template <> \
struct atomic<_type>: public details::atomic_integral<_type> \
_type operator=(_type val) volatile CDS_NOEXCEPT { return base_class::operator=(val); } \
_type operator=(_type val) CDS_NOEXCEPT { return base_class::operator=(val); } \
};
-#else
-# define CDS_DECLARE_ATOMIC_INTEGRAL( _type ) \
- template <> \
- struct atomic<_type>: public details::atomic_integral<_type> \
- { \
- private: \
- typedef details::atomic_integral<_type> base_class ; \
- public: \
- atomic() {} \
- atomic(_type val) CDS_NOEXCEPT : base_class(val) {} \
- _type operator=(_type val) volatile CDS_NOEXCEPT { return base_class::operator=(val); } \
- _type operator=(_type val) CDS_NOEXCEPT { return base_class::operator=(val); } \
- };
-#endif
CDS_DECLARE_ATOMIC_INTEGRAL(char)
CDS_DECLARE_ATOMIC_INTEGRAL(signed char)
template <typename T>
class atomic<T *>
-#ifndef CDS_CXX11_DELETE_DEFINITION_SUPPORT
- : details::atomic_noncopyable
-#endif
{
private:
T * volatile m_ptr;
return atomic_ops::atomic_fetch_sub_explicit( &m_ptr, offset, order );
}
-#ifdef CDS_CXX11_EXPLICITLY_DEFAULTED_FUNCTION_SUPPORT
atomic() = default;
-#else
- atomic() CDS_NOEXCEPT
- {}
-#endif
CDS_CONSTEXPR atomic(T * val) CDS_NOEXCEPT
: m_ptr( val )
{}
-#ifdef CDS_CXX11_DELETE_DEFINITION_SUPPORT
atomic(const atomic&) = delete;
atomic& operator=(const atomic&) = delete;
atomic& operator=(const atomic&) volatile = delete;
-#endif
T * operator=(T * val) volatile CDS_NOEXCEPT
{
typedef atomic<wchar_t> atomic_wchar_t;
- typedef atomic<cds::int_least8_t> atomic_int_least8_t;
- typedef atomic<cds::uint_least8_t> atomic_uint_least8_t;
- typedef atomic<cds::int_least16_t> atomic_int_least16_t;
- typedef atomic<cds::uint_least16_t> atomic_uint_least16_t;
- typedef atomic<cds::int_least32_t> atomic_int_least32_t;
- typedef atomic<cds::uint_least32_t> atomic_uint_least32_t;
- typedef atomic<cds::int_least64_t> atomic_int_least64_t;
- typedef atomic<cds::uint_least64_t> atomic_uint_least64_t;
- typedef atomic<cds::int_fast8_t> atomic_int_fast8_t;
- typedef atomic<cds::uint_fast8_t> atomic_uint_fast8_t;
- typedef atomic<cds::int_fast16_t> atomic_int_fast16_t;
- typedef atomic<cds::uint_fast16_t> atomic_uint_fast16_t;
- typedef atomic<cds::int_fast32_t> atomic_int_fast32_t;
- typedef atomic<cds::uint_fast32_t> atomic_uint_fast32_t;
- typedef atomic<cds::int_fast64_t> atomic_int_fast64_t;
- typedef atomic<cds::uint_fast64_t> atomic_uint_fast64_t;
+ typedef atomic<std::int_least8_t> atomic_int_least8_t;
+ typedef atomic<std::uint_least8_t> atomic_uint_least8_t;
+ typedef atomic<std::int_least16_t> atomic_int_least16_t;
+ typedef atomic<std::uint_least16_t> atomic_uint_least16_t;
+ typedef atomic<std::int_least32_t> atomic_int_least32_t;
+ typedef atomic<std::uint_least32_t> atomic_uint_least32_t;
+ typedef atomic<std::int_least64_t> atomic_int_least64_t;
+ typedef atomic<std::uint_least64_t> atomic_uint_least64_t;
+ typedef atomic<std::int_fast8_t> atomic_int_fast8_t;
+ typedef atomic<std::uint_fast8_t> atomic_uint_fast8_t;
+ typedef atomic<std::int_fast16_t> atomic_int_fast16_t;
+ typedef atomic<std::uint_fast16_t> atomic_uint_fast16_t;
+ typedef atomic<std::int_fast32_t> atomic_int_fast32_t;
+ typedef atomic<std::uint_fast32_t> atomic_uint_fast32_t;
+ typedef atomic<std::int_fast64_t> atomic_int_fast64_t;
+ typedef atomic<std::uint_fast64_t> atomic_uint_fast64_t;
typedef atomic<intptr_t> atomic_intptr_t;
typedef atomic<uintptr_t> atomic_uintptr_t;
typedef atomic<size_t> atomic_size_t;
typedef atomic<ptrdiff_t> atomic_ptrdiff_t;
- typedef atomic<cds::intmax_t> atomic_intmax_t;
- typedef atomic<cds::uintmax_t> atomic_uintmax_t;
+ typedef atomic<std::intmax_t> atomic_intmax_t;
+ typedef atomic<std::uintmax_t> atomic_uintmax_t;
template <class T>
static inline bool atomic_is_lock_free(const volatile atomic<T> * p) CDS_NOEXCEPT
return platform::atomic_flag_tas( &m_Flag, order );
}
-#ifdef CDS_CXX11_EXPLICITLY_DEFAULTED_FUNCTION_SUPPORT
atomic_flag() = default;
-#elif CDS_COMPILER != CDS_COMPILER_MSVC
- // MS VC generate error C2552 "non-aggregates cannot be initialized with initializer list"
- // when atomic_flag initializes with ATOMIC_FLAG_INIT
- atomic_flag()
- {}
-#endif
-#ifdef CDS_CXX11_DELETE_DEFINITION_SUPPORT
atomic_flag(const atomic_flag&) = delete;
atomic_flag& operator=(const atomic_flag&) = delete;
atomic_flag& operator=(const atomic_flag&) volatile = delete;
-#elif CDS_COMPILER != CDS_COMPILER_MSVC
- // MS VC generate error C2552 "non-aggregates cannot be initialized with initializer list"
- // when atomic_flag initializes with ATOMIC_FLAG_INIT
- private:
- atomic_flag(const atomic_flag&);
- atomic_flag& operator=(const atomic_flag&);
- atomic_flag& operator=(const atomic_flag&) volatile;
- public:
-#endif
platform::atomic_flag_type volatile m_Flag;
} atomic_flag;
platform::signal_fence( order );
}
-}} // namespace cds::cxx11_atomics
+}} // namespace cds::cxx11_atomic
//@endcond
-#endif // #ifndef __CDS_COMPILER_CXX11_ATOMIC_H
+#endif // #ifndef CDSLIB_COMPILER_CXX11_ATOMIC_H