# stdatomic.h

Go to the documentation of this file.

    00001 // -*- C++ -*- compatibility header.
    00002
    00003 // Copyright (C) 2008, 2009 Free Software Foundation, Inc.
    00004 //
    00005 // This file is part of the GNU ISO C++ Library.  This library is free
    00006 // software; you can redistribute it and/or modify it under the
    00007 // terms of the GNU General Public License as published by the
    00008 // Free Software Foundation; either version 3, or (at your option)
    00009 // any later version.
    00010
    00011 // This library is distributed in the hope that it will be useful,
    00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00014 // GNU General Public License for more details.
    00015
    00016 // Under Section 7 of GPL version 3, you are granted additional
    00017 // permissions described in the GCC Runtime Library Exception, version
    00018 // 3.1, as published by the Free Software Foundation.
    00019
    00020 // You should have received a copy of the GNU General Public License and
    00021 // a copy of the GCC Runtime Library Exception along with this program;
    00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    00023 // <http://www.gnu.org/licenses/>.
    00024
    00025 /** @file stdatomic.h
    00026  *  This is a Standard C++ Library header.
    00027  */
    00028
    00029 #include <bits/c++config.h>
    00030 #include <stddef.h>
    00031 #include <stdbool.h> // XXX need to define bool w/o stdbool.h in tr1/cstdbool
    00032
    00033 #ifndef _GLIBCXX_STDATOMIC_H
    00034 #define _GLIBCXX_STDATOMIC_H 1
    00035
    00036 _GLIBCXX_BEGIN_NAMESPACE(std)
    00037 _GLIBCXX_BEGIN_EXTERN_C
    00038
    00039   /**
    00040    * @defgroup atomics Atomics
    00041    *
    00042    * Components for performing atomic operations.
    00043    * @{
    00044    */
    00045
    00046   /// Enumeration for memory_order
    00047   typedef enum memory_order
    00048     {
    00049       memory_order_relaxed,
    00050       memory_order_consume,
    00051       memory_order_acquire,
    00052       memory_order_release,
    00053       memory_order_acq_rel,
    00054       memory_order_seq_cst
    00055     } memory_order;
    00056
    00057   // Base for atomic_flag.
    00058   typedef struct __atomic_flag_base
    00059   {
    00060     bool _M_i;
    00061   } __atomic_flag_base;
    00062
    00063 #define ATOMIC_FLAG_INIT { false }
    00064
    00065   /// 29.2 Lock-free Property
    00066 #if defined(_GLIBCXX_ATOMIC_BUILTINS_1) && defined(_GLIBCXX_ATOMIC_BUILTINS_2) \
    00067   && defined(_GLIBCXX_ATOMIC_BUILTINS_4) && defined(_GLIBCXX_ATOMIC_BUILTINS_8)
    00068 # define _GLIBCXX_ATOMIC_PROPERTY 2
    00069 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic2
    00070 #elif defined(_GLIBCXX_ATOMIC_BUILTINS_1)
    00071 # define _GLIBCXX_ATOMIC_PROPERTY 1
    00072 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic1
    00073 #else
    00074 # define _GLIBCXX_ATOMIC_PROPERTY 0
    00075 # define _GLIBCXX_ATOMIC_NAMESPACE __atomic0
    00076 #endif
    00077
    00078 #define ATOMIC_INTEGRAL_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY
    00079 #define ATOMIC_ADDRESS_LOCK_FREE _GLIBCXX_ATOMIC_PROPERTY
    00080
    00081   // Switch atomic integral base types based on C or C++.  In
    00082   // addition, for "C" only provide type-generic macros for atomic
    00083   // operations. (As C++ accomplishes the same thing with sets of
    00084   // overloaded functions.
    00085 #ifdef __cplusplus
    00086   inline namespace _GLIBCXX_ATOMIC_NAMESPACE { }
    00087 # include <bits/atomicfwd_cxx.h>
    00088 #else
    00089 # include <bits/atomicfwd_c.h>
    00090 #endif
    00091
    00092   // Typedefs for other atomic integral types.
    00093   typedef atomic_schar      atomic_int_least8_t;
    00094   typedef atomic_uchar      atomic_uint_least8_t;
    00095   typedef atomic_short      atomic_int_least16_t;
    00096   typedef atomic_ushort     atomic_uint_least16_t;
    00097   typedef atomic_int        atomic_int_least32_t;
    00098   typedef atomic_uint       atomic_uint_least32_t;
    00099   typedef atomic_llong      atomic_int_least64_t;
    00100   typedef atomic_ullong     atomic_uint_least64_t;
    00101
    00102   typedef atomic_schar      atomic_int_fast8_t;
    00103   typedef atomic_uchar      atomic_uint_fast8_t;
    00104   typedef atomic_short      atomic_int_fast16_t;
    00105   typedef atomic_ushort     atomic_uint_fast16_t;
    00106   typedef atomic_int        atomic_int_fast32_t;
    00107   typedef atomic_uint       atomic_uint_fast32_t;
    00108   typedef atomic_llong      atomic_int_fast64_t;
    00109   typedef atomic_ullong     atomic_uint_fast64_t;
    00110
    00111   typedef atomic_long       atomic_intptr_t;
    00112   typedef atomic_ulong      atomic_uintptr_t;
    00113
    00114   typedef atomic_long       atomic_ssize_t;
    00115   typedef atomic_ulong      atomic_size_t;
    00116
    00117   typedef atomic_llong      atomic_intmax_t;
    00118   typedef atomic_ullong     atomic_uintmax_t;
    00119
    00120   typedef atomic_long       atomic_ptrdiff_t;
    00121
    00122   // Accessor functions for base atomic_flag type.
    00123   bool
    00124   atomic_flag_test_and_set_explicit(volatile __atomic_flag_base*, memory_order);
    00125
    00126   inline bool
    00127   atomic_flag_test_and_set(volatile __atomic_flag_base* __a)
    00128   { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); }
    00129
    00130   void
    00131   atomic_flag_clear_explicit(volatile __atomic_flag_base*, memory_order);
    00132
    00133   inline void
    00134   atomic_flag_clear(volatile __atomic_flag_base* __a)
    00135   { atomic_flag_clear_explicit(__a, memory_order_seq_cst); }
    00136
    00137   void
    00138   __atomic_flag_wait_explicit(volatile __atomic_flag_base*, memory_order);
    00139
    00140   volatile __atomic_flag_base*
    00141   __atomic_flag_for_address(const volatile void* __z) __attribute__((const));
    00142
    00143   // Implementation specific defines.
    00144 #define _ATOMIC_LOAD_(__a, __x)                     \
    00145   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;   \
    00146      volatile atomic_flag* __g = __atomic_flag_for_address(__p);    \
    00147     __atomic_flag_wait_explicit(__g, __x);              \
    00148     __typeof__ _ATOMIC_MEMBER_ __r = *__p;              \
    00149     atomic_flag_clear_explicit(__g, __x);                   \
    00150     __r; })
    00151
    00152 #define _ATOMIC_STORE_(__a, __m, __x)                   \
    00153   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;   \
    00154     __typeof__(__m) __v = (__m);                        \
    00155     volatile atomic_flag* __g = __atomic_flag_for_address(__p);     \
    00156     __atomic_flag_wait_explicit(__g, __x);              \
    00157     *__p = __v;                             \
    00158     atomic_flag_clear_explicit(__g, __x);                   \
    00159     __v; })
    00160
    00161 #define _ATOMIC_MODIFY_(__a, __o, __m, __x)             \
    00162   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;   \
    00163     __typeof__(__m) __v = (__m);                        \
    00164     volatile atomic_flag* __g = __atomic_flag_for_address(__p);     \
    00165     __atomic_flag_wait_explicit(__g, __x);              \
    00166     __typeof__ _ATOMIC_MEMBER_ __r = *__p;              \
    00167     *__p __o __v;                               \
    00168     atomic_flag_clear_explicit(__g, __x);                   \
    00169     __r; })
    00170
    00171 #define _ATOMIC_CMPEXCHNG_(__a, __e, __m, __x)              \
    00172   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;   \
    00173     __typeof__(__e) __q = (__e);                        \
    00174     __typeof__(__m) __v = (__m);                        \
    00175     bool __r;                                   \
    00176     volatile atomic_flag* __g = __atomic_flag_for_address(__p);     \
    00177     __atomic_flag_wait_explicit(__g, __x);              \
    00178     __typeof__ _ATOMIC_MEMBER_ __t__ = *__p;                    \
    00179     if (__t__ == *__q) { *__p = __v; __r = true; }          \
    00180     else { *__q = __t__; __r = false; }                     \
    00181     atomic_flag_clear_explicit(__g, __x);                   \
    00182     __r; })
    00183
    00184   // @} group atomics
    00185
    00186 _GLIBCXX_END_EXTERN_C
    00187 _GLIBCXX_END_NAMESPACE
    00188
    00189 // Inject into global namespace. XXX
    00190 #if defined(__cplusplus) && !defined(_GLIBCXX_STDATOMIC)
    00191 using std::memory_order;
    00192 using std::memory_order_relaxed;
    00193 using std::memory_order_consume;
    00194 using std::memory_order_acquire;
    00195 using std::memory_order_release;
    00196 using std::memory_order_acq_rel;
    00197 using std::memory_order_seq_cst;
    00198 using std::atomic_flag;
    00199 using std::atomic_bool;
    00200 using std::atomic_char;
    00201 using std::atomic_schar;
    00202 using std::atomic_uchar;
    00203 using std::atomic_short;
    00204 using std::atomic_ushort;
    00205 using std::atomic_int;
    00206 using std::atomic_uint;
    00207 using std::atomic_long;
    00208 using std::atomic_ulong;
    00209 using std::atomic_llong;
    00210 using std::atomic_ullong;
    00211 using std::atomic_wchar_t;
    00212 using std::atomic_char16_t;
    00213 using std::atomic_char32_t;
    00214 using std::atomic_address;
    00215 using std::atomic;
    00216 #endif
    00217
    00218 #endif