remove intrusive specialization from exempt_ptr
[libcds.git] / cds / cxx11_atomic.h
index 8508fd8d8fcbbf77ea1b0c6b0687e3a886b60f68..bc33866ed66ec09ceee3fba965d5466b077d7d72 100644 (file)
@@ -8,86 +8,30 @@
 namespace cds {
 
 /// C++11 Atomic library support
-/** @ingroup cds_cxx11_stdlib_wrapper
-    <b>libcds</b> has an implementation of C++11 atomic library (header <tt><cds/cxx11_atomic.h></tt>)
-    specified in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf">N3242, p.29</a>.
-
-    This implementation has full support
-    - <tt>atomic<T></tt> class and its specializations for integral types and pointers
-    - <tt>atomic_flag</tt> class
-    - free <tt>atomic_xxx</tt> functions
-
-    Exclusions: the following features specified in C++11 standard are not implemented:
-    - Atomic emulation. The library implements only genuine atomic operations for supported processors
-    - Static initialization macros (like \p ATOMIC_FLAG_INIT and others)
-    - \p atomic_init functions
-
-    Internal atomic implementation is used when the standard library provided by compiler
-    has no C++11 <tt>\<atomic\></tt> header or it is not standard compliant,
-    or when \p CDS_USE_LIBCDS_ATOMIC preprocessor macro is explicitly defined in compiler command line.
-    The library defines \p CDS_ATOMIC macro that specifies atomic library namespace:
-    - \p std for compiler-provided <tt>\<atomic\></tt> library
-    - \p boost if you use <tt>boost.atomic</tt> library (see note below)
-    - \p cds::cxx11_atomic if internal \p libcds atomic implementation used
-
-    The library has internal atomic implementation for the following processor architectures:
-    - Intel and AMD x86 (32bit) and amd64 (64bit)
-    - Intel Itanium IA64 (64bit)
-    - UltraSparc (64bit)
-
-    Using \p CDS_ATOMIC macro you may call <tt>\<atomic\></tt> library functions and classes,
-    for example:
-    \code
-    CDS_ATOMIC::atomic<int> atomInt;
-    CDS_ATOMIC::atomic_store_explicit( &atomInt, 0, CDS_ATOMIC::memory_order_release );
-    \endcode
-
-    \par Microsoft Visual C++
-
-    MS Visual C++ has native <tt>\<atomic\></tt> header beginning from Visual C++ 2012.
-    However, MSVC++ 2012 has a quite inefficient implementation on atomic load/store
-    based on \p compare_exchange, so \p libcds does not use MSVC++ 2012 atomics.
-    The \p libcds library defines \p CDS_ATOMIC as
-    - \p cds::cxx11_atomic (internal implementation) for MS VC++ 2008, 2010, and 2012
-    - \p std for MS VC++ 2013 and above.
-
-    \par GCC
-
-    For GCC compiler the macro \p CDS_ATOMIC is defined as:
-    - \p cds::cxx11_atomic by default
-    - \p std if the compiler version is 4.6 and \p CDS_CXX11_ATOMIC_GCC is defined (see below)
-    - \p std for GCC 4.7 and above
-
-    GCC team implements full support for C++11 memory model in version 4.7
-    (see <a href="http://gcc.gnu.org/wiki/Atomic/GCCMM">http://gcc.gnu.org/wiki/Atomic/GCCMM</a>).
-    \p libcds uses its own implementation of C++11 <tt>\<atomic\></tt> library located in
-    file <tt><cds/cxx11_atomic.h></tt> for GCC version up to 4.6. This implementation almost conforms to C++11 standard draft
-    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf">N3242</a> (see exclusions above)
-    that is closest to final version.
-    However, GCC 4.6 has the implementation of <tt>\<atomic\></tt> header in its <tt>libstdc++</tt>
-    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
-    <tt>\<atomic\></tt> specifying \p CDS_CXX11_ATOMIC_GCC macro in g++ command line:
-    \code g++ -DCDS_CXX11_ATOMIC_GCC ... \endcode
-    GCC 4.6 atomic implementation does not support <tt>atomic<T></tt> for <b>any</b> type \p T. The linker
-    generates "undefined symbol" error for <tt>atomic<T></tt> if \p T is not an integral type or a pointer. It is
-    not essential for intrusive and non-intrusive containers represented in \p libcds.
-    However, cds::memory::michael memory allocator cannot be linked with GCC 4.6 <tt>\<atomic\></tt> header.
-    This error has been fixed in GCC 4.7.
-
-    \par Clang
-
-    The macro \p CDS_ATOMIC is defined as \p cds::cxx11_atomic.
-    \p libcds does not yet use native clang atomics.
-
-    \par boost::atomic
-
-    Beginning from version 1.54, <a href="http://boost.org">boost</a> library contains an implementation of atomic
-    sufficient for \p libcds.
-    You can compile \p libcds and your projects with <tt>boost.atomic</tt> specifying \p -DCDS_USE_BOOST_ATOMIC
-    in compiler's command line.
+/**
+    \p libcds can use the following implementations of the atomics:
+    - STL \p &lt;atomic&gt;. 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 &lt;atomic&gt; 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_atomics {
-}} // namespace cds::cxx11_atomics
+namespace cxx11_atomic {
+}} // namespace cds::cxx11_atomic
 
 //@cond
 #if defined(CDS_USE_BOOST_ATOMIC)
@@ -95,7 +39,7 @@ namespace cxx11_atomics {
 #   include <boost/version.hpp>
 #   if BOOST_VERSION >= 105400
 #       include <boost/atomic.hpp>
-#       define CDS_ATOMIC boost
+        namespace atomics = boost;
 #       define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace boost {
 #       define CDS_CXX11_ATOMIC_END_NAMESPACE }
 #   else
@@ -104,13 +48,13 @@ namespace cxx11_atomics {
 #elif defined(CDS_USE_LIBCDS_ATOMIC)
     // libcds atomic
 #   include <cds/compiler/cxx11_atomic.h>
-#   define CDS_ATOMIC cds::cxx11_atomics
-#   define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace cds { namespace cxx11_atomics {
+    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>
-#   define CDS_ATOMIC std
+    namespace atomics = std;
 #   define CDS_CXX11_ATOMIC_BEGIN_NAMESPACE namespace std {
 #   define CDS_CXX11_ATOMIC_END_NAMESPACE }
 #endif
@@ -132,7 +76,7 @@ namespace cds {
         class event_counter
         {
             //@cond
-            CDS_ATOMIC::atomic_size_t   m_counter;
+            atomics::atomic_size_t   m_counter;
             //@endcond
 
         public:
@@ -152,7 +96,7 @@ namespace cds {
                 value_type n    //< new value of the counter
             ) CDS_NOEXCEPT
             {
-                m_counter.exchange( n, CDS_ATOMIC::memory_order_relaxed );
+                m_counter.exchange( n, atomics::memory_order_relaxed );
                 return n;
             }
 
@@ -164,7 +108,7 @@ namespace cds {
                 size_t n    ///< addendum
             ) CDS_NOEXCEPT
             {
-                return m_counter.fetch_add( n, CDS_ATOMIC::memory_order_relaxed ) + n;
+                return m_counter.fetch_add( n, atomics::memory_order_relaxed ) + n;
             }
 
             /// Substraction
@@ -175,47 +119,47 @@ namespace cds {
                 size_t n    ///< subtrahend
             ) CDS_NOEXCEPT
             {
-                return m_counter.fetch_sub( n, CDS_ATOMIC::memory_order_relaxed ) - n;
+                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( CDS_ATOMIC::memory_order_relaxed );
+                return m_counter.load( atomics::memory_order_relaxed );
             }
 
             /// Preincrement
             size_t operator ++() CDS_NOEXCEPT
             {
-                return m_counter.fetch_add( 1, CDS_ATOMIC::memory_order_relaxed ) + 1;
+                return m_counter.fetch_add( 1, atomics::memory_order_relaxed ) + 1;
             }
             /// Postincrement
             size_t operator ++(int) CDS_NOEXCEPT
             {
-                return m_counter.fetch_add( 1, CDS_ATOMIC::memory_order_relaxed );
+                return m_counter.fetch_add( 1, atomics::memory_order_relaxed );
             }
 
             /// Predecrement
             size_t operator --() CDS_NOEXCEPT
             {
-                return m_counter.fetch_sub( 1, CDS_ATOMIC::memory_order_relaxed ) - 1;
+                return m_counter.fetch_sub( 1, atomics::memory_order_relaxed ) - 1;
             }
             /// Postdecrement
             size_t operator --(int) CDS_NOEXCEPT
             {
-                return m_counter.fetch_sub( 1, CDS_ATOMIC::memory_order_relaxed );
+                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( CDS_ATOMIC::memory_order_relaxed );
+                return m_counter.load( atomics::memory_order_relaxed );
             }
 
             /// Resets the counter to 0
             void reset() CDS_NOEXCEPT
             {
-                m_counter.store( 0, CDS_ATOMIC::memory_order_release );
+                m_counter.store( 0, atomics::memory_order_release );
             }
 
         };
@@ -228,7 +172,7 @@ namespace cds {
         class item_counter
         {
         public:
-            typedef CDS_ATOMIC::atomic_size_t   atomic_type ;   ///< atomic type used
+            typedef atomics::atomic_size_t   atomic_type ;   ///< atomic type used
             typedef size_t counter_type    ;   ///< Integral item counter type (size_t)
 
         private:
@@ -243,7 +187,7 @@ namespace cds {
             {}
 
             /// Returns current value of the counter
-            counter_type    value(CDS_ATOMIC::memory_order order = CDS_ATOMIC::memory_order_relaxed) const
+            counter_type    value(atomics::memory_order order = atomics::memory_order_relaxed) const
             {
                 return m_Counter.load( order );
             }
@@ -267,13 +211,13 @@ namespace cds {
             }
 
             /// Increments the counter. Semantics: postincrement
-            counter_type inc(CDS_ATOMIC::memory_order order = CDS_ATOMIC::memory_order_relaxed )
+            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(CDS_ATOMIC::memory_order order = CDS_ATOMIC::memory_order_relaxed)
+            counter_type dec(atomics::memory_order order = atomics::memory_order_relaxed)
             {
                 return m_Counter.fetch_sub( 1, order );
             }
@@ -301,7 +245,7 @@ namespace cds {
             }
 
             /// Resets count to 0
-            void reset(CDS_ATOMIC::memory_order order = CDS_ATOMIC::memory_order_relaxed)
+            void reset(atomics::memory_order order = atomics::memory_order_relaxed)
             {
                 m_Counter.store( 0, order );
             }
@@ -320,7 +264,7 @@ namespace cds {
             typedef size_t counter_type    ;  ///< Counter type
         public:
             /// Returns 0
-            counter_type    value(CDS_ATOMIC::memory_order /*order*/ = CDS_ATOMIC::memory_order_relaxed) const
+            counter_type    value(atomics::memory_order /*order*/ = atomics::memory_order_relaxed) const
             {
                 return 0;
             }
@@ -332,13 +276,13 @@ namespace cds {
             }
 
             /// Dummy increment. Always returns 0
-            size_t inc(CDS_ATOMIC::memory_order /*order*/ = CDS_ATOMIC::memory_order_relaxed)
+            size_t inc(atomics::memory_order /*order*/ = atomics::memory_order_relaxed)
             {
                 return 0;
             }
 
             /// Dummy increment. Always returns 0
-            size_t dec(CDS_ATOMIC::memory_order /*order*/ = CDS_ATOMIC::memory_order_relaxed)
+            size_t dec(atomics::memory_order /*order*/ = atomics::memory_order_relaxed)
             {
                 return 0;
             }
@@ -366,13 +310,10 @@ namespace cds {
             }
 
             /// Dummy function
-            void reset(CDS_ATOMIC::memory_order /*order*/ = CDS_ATOMIC::memory_order_relaxed)
+            void reset(atomics::memory_order /*order*/ = atomics::memory_order_relaxed)
             {}
         };
-
-
     }   // namespace atomicity
-
 }   // namespace cds
 
 #endif // #ifndef __CDS_CXX11_ATOMIC_H