+//$$CDS-header$$
+
+#ifndef __CDS_CXX11_ATOMIC_H
+#define __CDS_CXX11_ATOMIC_H
+
+#include <cds/details/defs.h>
+
+namespace cds {
+
+/// C++11 Atomic library support
+/**
+ \p libcds can use the following implementations of the atomics:
+ - STL \p <atomic>. This is used by default
+ - \p boost.atomic for boost 1.54 and above. To use it you should define \p CDS_USE_BOOST_ATOMIC for
+ your compiler invocation, for example, for gcc specify \p -DCDS_USE_BOOST_ATOMIC
+ in command line
+ - \p libcds implementation of atomic operation according to C++11 standard as
+ specified in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf">N3242, p.29</a>.
+ \p libcds implementation is not the full standard compliant, it provides only C++ part of standard,
+ for example, \p libcds has no static initialization of the atomic variables and some other C features.
+ However, that imlementation is enough for the library purposes. Supported architecture: x86, amd64,
+ ia64 (Itanium) 64bit, 64bit Sparc. To use \p libcds atomic you should define \p CDS_USE_LIBCDS_ATOMIC
+ in the compiler command line (\p -DCDS_USE_LIBCDS_ATOMIC for gcc/clang).
+
+ @note For Clang compiler \p libcds do not use compiler-provided \p <atomic> due some problems.
+ Instead, \p libcds atomic is used by default, or you can try to use \p boost.atomic.
+
+ The library defines \p atomics alias for atomic namespace:
+ - <tt>namespace atomics = std</tt> for STL
+ - <tt>namespace atomics = boost</tt> for \p boost.atomic
+ - <tt>namespace atomics = cds::cxx11_atomic</tt> for library-provided atomic implementation
+*/
+namespace cxx11_atomic {
+}} // namespace cds::cxx11_atomic
+
+//@cond
+#if defined(CDS_USE_BOOST_ATOMIC)
+ // boost atomic
+# include <boost/version.hpp>
+# if BOOST_VERSION >= 105400
+# include <boost/atomic.hpp>
+ namespace atomics = boost;
+# define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace boost {
+# define CDS_CXX11_ATOMIC_END_NAMESPACE }
+# else
+# error "Boost version 1.54 or above is needed for boost.atomic"
+# endif
+#elif defined(CDS_USE_LIBCDS_ATOMIC)
+ // libcds atomic
+# include <cds/compiler/cxx11_atomic.h>
+ namespace atomics = cds::cxx11_atomic;
+# define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace cds { namespace cxx11_atomic {
+# define CDS_CXX11_ATOMIC_END_NAMESPACE }}
+#else
+ // Compiler provided C++11 atomic
+# include <atomic>
+ namespace atomics = std;
+# define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace std {
+# define CDS_CXX11_ATOMIC_END_NAMESPACE }
+#endif
+//@endcond
+
+namespace cds {
+
+ /// Atomic primitives
+ /**
+ This namespace contains useful primitives derived from <tt>std::atomic</tt>.
+ */
+ namespace atomicity {
+
+ /// Atomic event counter.
+ /**
+ This class is based on <tt>std::atomic_size_t</tt>.
+ It uses relaxed memory ordering \p memory_order_relaxed and may be used as a statistic counter.
+ */
+ class event_counter
+ {
+ //@cond
+ atomics::atomic_size_t m_counter;
+ //@endcond
+
+ public:
+ typedef size_t value_type ; ///< Type of counter
+
+ public:
+ // Initializes event counter with zero
+ event_counter() CDS_NOEXCEPT
+ : m_counter(size_t(0))
+ {}
+
+ /// Assign operator
+ /**
+ Returns \p n.
+ */
+ value_type operator =(
+ value_type n //< new value of the counter
+ ) CDS_NOEXCEPT
+ {
+ m_counter.exchange( n, atomics::memory_order_relaxed );
+ return n;
+ }
+
+ /// Addition
+ /**
+ Returns new value of the atomic counter.
+ */
+ size_t operator +=(
+ size_t n ///< addendum
+ ) CDS_NOEXCEPT
+ {
+ return m_counter.fetch_add( n, atomics::memory_order_relaxed ) + n;
+ }
+
+ /// Substraction
+ /**
+ Returns new value of the atomic counter.
+ */
+ size_t operator -=(
+ size_t n ///< subtrahend
+ ) CDS_NOEXCEPT
+ {
+ return m_counter.fetch_sub( n, atomics::memory_order_relaxed ) - n;
+ }
+
+ /// Get current value of the counter
+ operator size_t () const CDS_NOEXCEPT
+ {
+ return m_counter.load( atomics::memory_order_relaxed );
+ }
+
+ /// Preincrement
+ size_t operator ++() CDS_NOEXCEPT
+ {
+ return m_counter.fetch_add( 1, atomics::memory_order_relaxed ) + 1;
+ }
+ /// Postincrement
+ size_t operator ++(int) CDS_NOEXCEPT
+ {
+ return m_counter.fetch_add( 1, atomics::memory_order_relaxed );
+ }
+
+ /// Predecrement
+ size_t operator --() CDS_NOEXCEPT
+ {
+ return m_counter.fetch_sub( 1, atomics::memory_order_relaxed ) - 1;
+ }
+ /// Postdecrement
+ size_t operator --(int) CDS_NOEXCEPT
+ {
+ return m_counter.fetch_sub( 1, atomics::memory_order_relaxed );
+ }
+
+ /// Get current value of the counter
+ size_t get() const CDS_NOEXCEPT
+ {
+ return m_counter.load( atomics::memory_order_relaxed );
+ }
+
+ /// Resets the counter to 0
+ void reset() CDS_NOEXCEPT
+ {
+ m_counter.store( 0, atomics::memory_order_release );
+ }
+
+ };
+
+ /// Atomic item counter
+ /**
+ This class is simplified interface around <tt>std::atomic_size_t</tt>.
+ The class supports getting of current value of the counter and increment/decrement its value.
+ */
+ class item_counter
+ {
+ public:
+ typedef atomics::atomic_size_t atomic_type ; ///< atomic type used
+ typedef size_t counter_type ; ///< Integral item counter type (size_t)
+
+ private:
+ //@cond
+ atomic_type m_Counter ; ///< Atomic item counter
+ //@endcond
+
+ public:
+ /// Default ctor initializes the counter to zero.
+ item_counter()
+ : m_Counter(counter_type(0))
+ {}
+
+ /// Returns current value of the counter
+ counter_type value(atomics::memory_order order = atomics::memory_order_relaxed) const
+ {
+ return m_Counter.load( order );
+ }
+
+ /// Same as \ref value() with relaxed memory ordering
+ operator counter_type() const
+ {
+ return value();
+ }
+
+ /// Returns underlying atomic interface
+ atomic_type& getAtomic()
+ {
+ return m_Counter;
+ }
+
+ /// Returns underlying atomic interface (const)
+ const atomic_type& getAtomic() const
+ {
+ return m_Counter;
+ }
+
+ /// Increments the counter. Semantics: postincrement
+ counter_type inc(atomics::memory_order order = atomics::memory_order_relaxed )
+ {
+ return m_Counter.fetch_add( 1, order );
+ }
+
+ /// Decrements the counter. Semantics: postdecrement
+ counter_type dec(atomics::memory_order order = atomics::memory_order_relaxed)
+ {
+ return m_Counter.fetch_sub( 1, order );
+ }
+
+ /// Preincrement
+ counter_type operator ++()
+ {
+ return inc() + 1;
+ }
+ /// Postincrement
+ counter_type operator ++(int)
+ {
+ return inc();
+ }
+
+ /// Predecrement
+ counter_type operator --()
+ {
+ return dec() - 1;
+ }
+ /// Postdecrement
+ counter_type operator --(int)
+ {
+ return dec();
+ }
+
+ /// Resets count to 0
+ void reset(atomics::memory_order order = atomics::memory_order_relaxed)
+ {
+ m_Counter.store( 0, order );
+ }
+ };
+
+ /// Empty item counter
+ /**
+ This class may be used instead of \ref item_counter when you do not need full \ref item_counter interface.
+ All methods of the class is empty and returns 0.
+
+ The object of this class should not be used in data structure that behavior significantly depends on item counting
+ (for example, in many hash map implementation).
+ */
+ class empty_item_counter {
+ public:
+ typedef size_t counter_type ; ///< Counter type
+ public:
+ /// Returns 0
+ counter_type value(atomics::memory_order /*order*/ = atomics::memory_order_relaxed) const
+ {
+ return 0;
+ }
+
+ /// Same as \ref value(), always returns 0.
+ operator counter_type() const
+ {
+ return value();
+ }
+
+ /// Dummy increment. Always returns 0
+ size_t inc(atomics::memory_order /*order*/ = atomics::memory_order_relaxed)
+ {
+ return 0;
+ }
+
+ /// Dummy increment. Always returns 0
+ size_t dec(atomics::memory_order /*order*/ = atomics::memory_order_relaxed)
+ {
+ return 0;
+ }
+
+ /// Dummy pre-increment. Always returns 0
+ size_t operator ++()
+ {
+ return 0;
+ }
+ /// Dummy post-increment. Always returns 0
+ size_t operator ++(int)
+ {
+ return 0;
+ }
+
+ /// Dummy pre-decrement. Always returns 0
+ size_t operator --()
+ {
+ return 0;
+ }
+ /// Dummy post-decrement. Always returns 0
+ size_t operator --(int)
+ {
+ return 0;
+ }
+
+ /// Dummy function
+ void reset(atomics::memory_order /*order*/ = atomics::memory_order_relaxed)
+ {}
+ };
+ } // namespace atomicity
+} // namespace cds
+
+#endif // #ifndef __CDS_CXX11_ATOMIC_H