3 #ifndef __CDS_CXX11_ATOMIC_H
4 #define __CDS_CXX11_ATOMIC_H
6 #include <cds/details/defs.h>
10 /// C++11 Atomic library support
12 \p libcds can use the following implementations of the atomics:
13 - STL <tt><atomic></tt>. This is used by default
14 - \p boost.atomic for boost 1.54 and above. To use it you should define \p CDS_USE_BOOST_ATOMIC for
15 your compiler invocation, for example, for gcc specify \p -DCDS_USE_BOOST_ATOMIC
17 - \p libcds implementation of atomic operation according to C++11 standard as
18 specified in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf">N3242, p.29</a>.
19 \p libcds implementation is not the full standard compliant, it provides only C++ part of standard,
20 for example, \p libcds has no static initialization of the atomic variables and some other C features.
21 However, that imlementation is enough for the library purposes. Supported architecture: x86, amd64,
22 ia64 (Itanium) 64bit, 64bit Sparc. To use \p libcds atomic you should define \p CDS_USE_LIBCDS_ATOMIC
23 in the compiler command line (\p -DCDS_USE_LIBCDS_ATOMIC for gcc/clang).
25 @note For Clang compiler \p libcds do not use compiler-provided <tt><atomic></tt> due some problems.
26 Instead, \p libcds atomic is used by default, or you can try to use \p boost.atomic.
28 The library defines \p atomics alias for atomic namespace:
29 - <tt>namespace atomics = std</tt> for STL
30 - <tt>namespace atomics = boost</tt> for \p boost.atomic
31 - <tt>namespace atomics = cds::cxx11_atomic for library-provided atomic implementation
33 namespace cxx11_atomic {
34 }} // namespace cds::cxx11_atomic
37 #if defined(CDS_USE_BOOST_ATOMIC)
39 # include <boost/version.hpp>
40 # if BOOST_VERSION >= 105400
41 # include <boost/atomic.hpp>
42 namespace atomics = boost;
43 # define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace boost {
44 # define CDS_CXX11_ATOMIC_END_NAMESPACE }
46 # error "Boost version 1.54 or above is needed for boost.atomic"
48 #elif defined(CDS_USE_LIBCDS_ATOMIC)
50 # include <cds/compiler/cxx11_atomic.h>
51 namespace atomics = cds::cxx11_atomic;
52 # define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace cds { namespace cxx11_atomic {
53 # define CDS_CXX11_ATOMIC_END_NAMESPACE }}
55 // Compiler provided C++11 atomic
57 namespace atomics = std;
58 # define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace std {
59 # define CDS_CXX11_ATOMIC_END_NAMESPACE }
67 This namespace contains useful primitives derived from <tt>std::atomic</tt>.
71 /// Atomic event counter.
73 This class is based on <tt>std::atomic_size_t</tt>.
74 It uses relaxed memory ordering \p memory_order_relaxed and may be used as a statistic counter.
79 atomics::atomic_size_t m_counter;
83 typedef size_t value_type ; ///< Type of counter
86 // Initializes event counter with zero
87 event_counter() CDS_NOEXCEPT
88 : m_counter(size_t(0))
95 value_type operator =(
96 value_type n //< new value of the counter
99 m_counter.exchange( n, atomics::memory_order_relaxed );
105 Returns new value of the atomic counter.
108 size_t n ///< addendum
111 return m_counter.fetch_add( n, atomics::memory_order_relaxed ) + n;
116 Returns new value of the atomic counter.
119 size_t n ///< subtrahend
122 return m_counter.fetch_sub( n, atomics::memory_order_relaxed ) - n;
125 /// Get current value of the counter
126 operator size_t () const CDS_NOEXCEPT
128 return m_counter.load( atomics::memory_order_relaxed );
132 size_t operator ++() CDS_NOEXCEPT
134 return m_counter.fetch_add( 1, atomics::memory_order_relaxed ) + 1;
137 size_t operator ++(int) CDS_NOEXCEPT
139 return m_counter.fetch_add( 1, atomics::memory_order_relaxed );
143 size_t operator --() CDS_NOEXCEPT
145 return m_counter.fetch_sub( 1, atomics::memory_order_relaxed ) - 1;
148 size_t operator --(int) CDS_NOEXCEPT
150 return m_counter.fetch_sub( 1, atomics::memory_order_relaxed );
153 /// Get current value of the counter
154 size_t get() const CDS_NOEXCEPT
156 return m_counter.load( atomics::memory_order_relaxed );
159 /// Resets the counter to 0
160 void reset() CDS_NOEXCEPT
162 m_counter.store( 0, atomics::memory_order_release );
167 /// Atomic item counter
169 This class is simplified interface around <tt>std::atomic_size_t</tt>.
170 The class supports getting of current value of the counter and increment/decrement its value.
175 typedef atomics::atomic_size_t atomic_type ; ///< atomic type used
176 typedef size_t counter_type ; ///< Integral item counter type (size_t)
180 atomic_type m_Counter ; ///< Atomic item counter
184 /// Default ctor initializes the counter to zero.
186 : m_Counter(counter_type(0))
189 /// Returns current value of the counter
190 counter_type value(atomics::memory_order order = atomics::memory_order_relaxed) const
192 return m_Counter.load( order );
195 /// Same as \ref value() with relaxed memory ordering
196 operator counter_type() const
201 /// Returns underlying atomic interface
202 atomic_type& getAtomic()
207 /// Returns underlying atomic interface (const)
208 const atomic_type& getAtomic() const
213 /// Increments the counter. Semantics: postincrement
214 counter_type inc(atomics::memory_order order = atomics::memory_order_relaxed )
216 return m_Counter.fetch_add( 1, order );
219 /// Decrements the counter. Semantics: postdecrement
220 counter_type dec(atomics::memory_order order = atomics::memory_order_relaxed)
222 return m_Counter.fetch_sub( 1, order );
226 counter_type operator ++()
231 counter_type operator ++(int)
237 counter_type operator --()
242 counter_type operator --(int)
247 /// Resets count to 0
248 void reset(atomics::memory_order order = atomics::memory_order_relaxed)
250 m_Counter.store( 0, order );
254 /// Empty item counter
256 This class may be used instead of \ref item_counter when you do not need full \ref item_counter interface.
257 All methods of the class is empty and returns 0.
259 The object of this class should not be used in data structure that behavior significantly depends on item counting
260 (for example, in many hash map implementation).
262 class empty_item_counter {
264 typedef size_t counter_type ; ///< Counter type
267 counter_type value(atomics::memory_order /*order*/ = atomics::memory_order_relaxed) const
272 /// Same as \ref value(), always returns 0.
273 operator counter_type() const
278 /// Dummy increment. Always returns 0
279 size_t inc(atomics::memory_order /*order*/ = atomics::memory_order_relaxed)
284 /// Dummy increment. Always returns 0
285 size_t dec(atomics::memory_order /*order*/ = atomics::memory_order_relaxed)
290 /// Dummy pre-increment. Always returns 0
295 /// Dummy post-increment. Always returns 0
296 size_t operator ++(int)
301 /// Dummy pre-decrement. Always returns 0
306 /// Dummy post-decrement. Always returns 0
307 size_t operator --(int)
313 void reset(atomics::memory_order /*order*/ = atomics::memory_order_relaxed)
316 } // namespace atomicity
319 #endif // #ifndef __CDS_CXX11_ATOMIC_H