3 #ifndef __CDS_CXX11_ATOMIC_H
4 #define __CDS_CXX11_ATOMIC_H
6 #include <cds/details/defs.h>
10 /// C++11 Atomic library support
11 /** @ingroup cds_cxx11_stdlib_wrapper
12 <b>libcds</b> has an implementation of C++11 atomic library (header <tt><cds/cxx11_atomic.h></tt>)
13 specified in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf">N3242, p.29</a>.
15 This implementation has full support
16 - <tt>atomic<T></tt> class and its specializations for integral types and pointers
17 - <tt>atomic_flag</tt> class
18 - free <tt>atomic_xxx</tt> functions
20 Exclusions: the following features specified in C++11 standard are not implemented:
21 - Atomic emulation. The library implements only genuine atomic operations for supported processors
22 - Static initialization macros (like \p ATOMIC_FLAG_INIT and others)
23 - \p atomic_init functions
25 Internal atomic implementation is used when the standard library provided by compiler
26 has no C++11 <tt>\<atomic\></tt> header or it is not standard compliant,
27 or when \p CDS_USE_LIBCDS_ATOMIC preprocessor macro is explicitly defined in compiler command line.
28 The library defines \p CDS_ATOMIC macro that specifies atomic library namespace:
29 - \p std for compiler-provided <tt>\<atomic\></tt> library
30 - \p boost if you use <tt>boost.atomic</tt> library (see note below)
31 - \p cds::cxx11_atomic if internal \p libcds atomic implementation used
33 The library has internal atomic implementation for the following processor architectures:
34 - Intel and AMD x86 (32bit) and amd64 (64bit)
35 - Intel Itanium IA64 (64bit)
38 Using \p CDS_ATOMIC macro you may call <tt>\<atomic\></tt> library functions and classes,
41 CDS_ATOMIC::atomic<int> atomInt;
42 CDS_ATOMIC::atomic_store_explicit( &atomInt, 0, CDS_ATOMIC::memory_order_release );
45 \par Microsoft Visual C++
47 MS Visual C++ has native <tt>\<atomic\></tt> header beginning from Visual C++ 2012.
48 However, MSVC++ 2012 has a quite inefficient implementation on atomic load/store
49 based on \p compare_exchange, so \p libcds does not use MSVC++ 2012 atomics.
50 The \p libcds library defines \p CDS_ATOMIC as
51 - \p cds::cxx11_atomic (internal implementation) for MS VC++ 2008, 2010, and 2012
52 - \p std for MS VC++ 2013 and above.
56 For GCC compiler the macro \p CDS_ATOMIC is defined as:
57 - \p cds::cxx11_atomic by default
58 - \p std if the compiler version is 4.6 and \p CDS_CXX11_ATOMIC_GCC is defined (see below)
59 - \p std for GCC 4.7 and above
61 GCC team implements full support for C++11 memory model in version 4.7
62 (see <a href="http://gcc.gnu.org/wiki/Atomic/GCCMM">http://gcc.gnu.org/wiki/Atomic/GCCMM</a>).
63 \p libcds uses its own implementation of C++11 <tt>\<atomic\></tt> library located in
64 file <tt><cds/cxx11_atomic.h></tt> for GCC version up to 4.6. This implementation almost conforms to C++11 standard draft
65 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf">N3242</a> (see exclusions above)
66 that is closest to final version.
67 However, GCC 4.6 has the implementation of <tt>\<atomic\></tt> header in its <tt>libstdc++</tt>
68 that is built on <tt>__sync_xxx</tt> (or <tt>__atomic_xxx</tt>) built-in functions. You can use <b>libcds</b> with GCC 4.6
69 <tt>\<atomic\></tt> specifying \p CDS_CXX11_ATOMIC_GCC macro in g++ command line:
70 \code g++ -DCDS_CXX11_ATOMIC_GCC ... \endcode
71 GCC 4.6 atomic implementation does not support <tt>atomic<T></tt> for <b>any</b> type \p T. The linker
72 generates "undefined symbol" error for <tt>atomic<T></tt> if \p T is not an integral type or a pointer. It is
73 not essential for intrusive and non-intrusive containers represented in \p libcds.
74 However, cds::memory::michael memory allocator cannot be linked with GCC 4.6 <tt>\<atomic\></tt> header.
75 This error has been fixed in GCC 4.7.
79 The macro \p CDS_ATOMIC is defined as \p cds::cxx11_atomic.
80 \p libcds does not yet use native clang atomics.
84 Beginning from version 1.54, <a href="http://boost.org">boost</a> library contains an implementation of atomic
85 sufficient for \p libcds.
86 You can compile \p libcds and your projects with <tt>boost.atomic</tt> specifying \p -DCDS_USE_BOOST_ATOMIC
87 in compiler's command line.
89 namespace cxx11_atomics {
90 }} // namespace cds::cxx11_atomics
93 #if defined(CDS_USE_BOOST_ATOMIC)
95 # include <boost/version.hpp>
96 # if BOOST_VERSION >= 105400
97 # include <boost/atomic.hpp>
98 # define CDS_ATOMIC boost
99 # define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace boost {
100 # define CDS_CXX11_ATOMIC_END_NAMESPACE }
102 # error "Boost version 1.54 or above is needed for boost.atomic"
104 #elif defined(CDS_USE_LIBCDS_ATOMIC)
106 # include <cds/compiler/cxx11_atomic.h>
107 # define CDS_ATOMIC cds::cxx11_atomics
108 # define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace cds { namespace cxx11_atomics {
109 # define CDS_CXX11_ATOMIC_END_NAMESPACE }}
111 // Compiler provided C++11 atomic
113 # define CDS_ATOMIC std
114 # define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace std {
115 # define CDS_CXX11_ATOMIC_END_NAMESPACE }
121 /// Atomic primitives
123 This namespace contains useful primitives derived from <tt>std::atomic</tt>.
125 namespace atomicity {
127 /// Atomic event counter.
129 This class is based on <tt>std::atomic_size_t</tt>.
130 It uses relaxed memory ordering \p memory_order_relaxed and may be used as a statistic counter.
135 CDS_ATOMIC::atomic_size_t m_counter;
139 typedef size_t value_type ; ///< Type of counter
142 // Initializes event counter with zero
143 event_counter() CDS_NOEXCEPT
144 : m_counter(size_t(0))
151 value_type operator =(
152 value_type n //< new value of the counter
155 m_counter.exchange( n, CDS_ATOMIC::memory_order_relaxed );
161 Returns new value of the atomic counter.
164 size_t n ///< addendum
167 return m_counter.fetch_add( n, CDS_ATOMIC::memory_order_relaxed ) + n;
172 Returns new value of the atomic counter.
175 size_t n ///< subtrahend
178 return m_counter.fetch_sub( n, CDS_ATOMIC::memory_order_relaxed ) - n;
181 /// Get current value of the counter
182 operator size_t () const CDS_NOEXCEPT
184 return m_counter.load( CDS_ATOMIC::memory_order_relaxed );
188 size_t operator ++() CDS_NOEXCEPT
190 return m_counter.fetch_add( 1, CDS_ATOMIC::memory_order_relaxed ) + 1;
193 size_t operator ++(int) CDS_NOEXCEPT
195 return m_counter.fetch_add( 1, CDS_ATOMIC::memory_order_relaxed );
199 size_t operator --() CDS_NOEXCEPT
201 return m_counter.fetch_sub( 1, CDS_ATOMIC::memory_order_relaxed ) - 1;
204 size_t operator --(int) CDS_NOEXCEPT
206 return m_counter.fetch_sub( 1, CDS_ATOMIC::memory_order_relaxed );
209 /// Get current value of the counter
210 size_t get() const CDS_NOEXCEPT
212 return m_counter.load( CDS_ATOMIC::memory_order_relaxed );
215 /// Resets the counter to 0
216 void reset() CDS_NOEXCEPT
218 m_counter.store( 0, CDS_ATOMIC::memory_order_release );
223 /// Atomic item counter
225 This class is simplified interface around <tt>std::atomic_size_t</tt>.
226 The class supports getting of current value of the counter and increment/decrement its value.
231 typedef CDS_ATOMIC::atomic_size_t atomic_type ; ///< atomic type used
232 typedef size_t counter_type ; ///< Integral item counter type (size_t)
236 atomic_type m_Counter ; ///< Atomic item counter
240 /// Default ctor initializes the counter to zero.
242 : m_Counter(counter_type(0))
245 /// Returns current value of the counter
246 counter_type value(CDS_ATOMIC::memory_order order = CDS_ATOMIC::memory_order_relaxed) const
248 return m_Counter.load( order );
251 /// Same as \ref value() with relaxed memory ordering
252 operator counter_type() const
257 /// Returns underlying atomic interface
258 atomic_type& getAtomic()
263 /// Returns underlying atomic interface (const)
264 const atomic_type& getAtomic() const
269 /// Increments the counter. Semantics: postincrement
270 counter_type inc(CDS_ATOMIC::memory_order order = CDS_ATOMIC::memory_order_relaxed )
272 return m_Counter.fetch_add( 1, order );
275 /// Decrements the counter. Semantics: postdecrement
276 counter_type dec(CDS_ATOMIC::memory_order order = CDS_ATOMIC::memory_order_relaxed)
278 return m_Counter.fetch_sub( 1, order );
282 counter_type operator ++()
287 counter_type operator ++(int)
293 counter_type operator --()
298 counter_type operator --(int)
303 /// Resets count to 0
304 void reset(CDS_ATOMIC::memory_order order = CDS_ATOMIC::memory_order_relaxed)
306 m_Counter.store( 0, order );
310 /// Empty item counter
312 This class may be used instead of \ref item_counter when you do not need full \ref item_counter interface.
313 All methods of the class is empty and returns 0.
315 The object of this class should not be used in data structure that behavior significantly depends on item counting
316 (for example, in many hash map implementation).
318 class empty_item_counter {
320 typedef size_t counter_type ; ///< Counter type
323 counter_type value(CDS_ATOMIC::memory_order /*order*/ = CDS_ATOMIC::memory_order_relaxed) const
328 /// Same as \ref value(), always returns 0.
329 operator counter_type() const
334 /// Dummy increment. Always returns 0
335 size_t inc(CDS_ATOMIC::memory_order /*order*/ = CDS_ATOMIC::memory_order_relaxed)
340 /// Dummy increment. Always returns 0
341 size_t dec(CDS_ATOMIC::memory_order /*order*/ = CDS_ATOMIC::memory_order_relaxed)
346 /// Dummy pre-increment. Always returns 0
351 /// Dummy post-increment. Always returns 0
352 size_t operator ++(int)
357 /// Dummy pre-decrement. Always returns 0
362 /// Dummy post-decrement. Always returns 0
363 size_t operator --(int)
369 void reset(CDS_ATOMIC::memory_order /*order*/ = CDS_ATOMIC::memory_order_relaxed)
374 } // namespace atomicity
378 #endif // #ifndef __CDS_CXX11_ATOMIC_H