libstdc++

atomic_0.h

Go to the documentation of this file.
00001 // -*- C++ -*- header.
00002 
00003 // Copyright (C) 2008, 2009, 2010, 2011
00004 // Free Software Foundation, Inc.
00005 //
00006 // This file is part of the GNU ISO C++ Library.  This library is free
00007 // software; you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the
00009 // Free Software Foundation; either version 3, or (at your option)
00010 // any later version.
00011 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 
00017 // Under Section 7 of GPL version 3, you are granted additional
00018 // permissions described in the GCC Runtime Library Exception, version
00019 // 3.1, as published by the Free Software Foundation.
00020 
00021 // You should have received a copy of the GNU General Public License and
00022 // a copy of the GCC Runtime Library Exception along with this program;
00023 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00024 // <http://www.gnu.org/licenses/>.
00025 
00026 /** @file bits/atomic_0.h
00027  *  This is an internal header file, included by other library headers.
00028  *  Do not attempt to use it directly. @headername{atomic}
00029  */
00030 
00031 #ifndef _GLIBCXX_ATOMIC_0_H
00032 #define _GLIBCXX_ATOMIC_0_H 1
00033 
00034 #pragma GCC system_header
00035 
00036 namespace std _GLIBCXX_VISIBILITY(default)
00037 {
00038 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00039 
00040 // 0 == __atomic0 == Never lock-free
00041 namespace __atomic0
00042 {
00043   _GLIBCXX_BEGIN_EXTERN_C
00044 
00045   void
00046   atomic_flag_clear_explicit(__atomic_flag_base*, memory_order)
00047   _GLIBCXX_NOTHROW;
00048 
00049   void
00050   __atomic_flag_wait_explicit(__atomic_flag_base*, memory_order)
00051   _GLIBCXX_NOTHROW;
00052 
00053   _GLIBCXX_CONST __atomic_flag_base*
00054   __atomic_flag_for_address(const volatile void* __z) _GLIBCXX_NOTHROW;
00055 
00056   _GLIBCXX_END_EXTERN_C
00057 
00058   // Implementation specific defines.
00059 #define _ATOMIC_MEMBER_ _M_i
00060 
00061   // Implementation specific defines.
00062 #define _ATOMIC_LOAD_(__a, __x)                        \
00063   ({typedef __typeof__(_ATOMIC_MEMBER_) __i_type;                          \
00064     __i_type* __p = &_ATOMIC_MEMBER_;                      \
00065     __atomic_flag_base* __g = __atomic_flag_for_address(__p);          \
00066     __atomic_flag_wait_explicit(__g, __x);                 \
00067     __i_type __r = *__p;                           \
00068     atomic_flag_clear_explicit(__g, __x);                      \
00069     __r; })
00070 
00071 #define _ATOMIC_STORE_(__a, __n, __x)                      \
00072   ({typedef __typeof__(_ATOMIC_MEMBER_) __i_type;                          \
00073     __i_type* __p = &_ATOMIC_MEMBER_;                      \
00074     __typeof__(__n) __w = (__n);                           \
00075     __atomic_flag_base* __g = __atomic_flag_for_address(__p);          \
00076     __atomic_flag_wait_explicit(__g, __x);                 \
00077     *__p = __w;                                \
00078     atomic_flag_clear_explicit(__g, __x);                      \
00079     __w; })
00080 
00081 #define _ATOMIC_MODIFY_(__a, __o, __n, __x)                \
00082   ({typedef __typeof__(_ATOMIC_MEMBER_) __i_type;                          \
00083     __i_type* __p = &_ATOMIC_MEMBER_;                      \
00084     __typeof__(__n) __w = (__n);                           \
00085     __atomic_flag_base* __g = __atomic_flag_for_address(__p);          \
00086     __atomic_flag_wait_explicit(__g, __x);                 \
00087     __i_type __r = *__p;                               \
00088     *__p __o __w;                                  \
00089     atomic_flag_clear_explicit(__g, __x);                      \
00090     __r; })
00091 
00092 #define _ATOMIC_CMPEXCHNG_(__a, __e, __n, __x)                 \
00093   ({typedef __typeof__(_ATOMIC_MEMBER_) __i_type;                          \
00094     __i_type* __p = &_ATOMIC_MEMBER_;                      \
00095     __typeof__(__e) __q = (__e);                           \
00096     __typeof__(__n) __w = (__n);                           \
00097     bool __r;                                      \
00098     __atomic_flag_base* __g = __atomic_flag_for_address(__p);          \
00099     __atomic_flag_wait_explicit(__g, __x);                 \
00100     __i_type __t = *__p;                               \
00101     if (*__q == __t)                               \
00102       {                                    \
00103     *__p = (__i_type)__w;                          \
00104     __r = true;                            \
00105       }                                    \
00106     else { *__q = __t; __r = false; }                          \
00107     atomic_flag_clear_explicit(__g, __x);                      \
00108     __r; })
00109 
00110 
00111   /// atomic_flag
00112   struct atomic_flag : public __atomic_flag_base
00113   {
00114     atomic_flag() = default;
00115     ~atomic_flag() = default;
00116     atomic_flag(const atomic_flag&) = delete;
00117     atomic_flag& operator=(const atomic_flag&) = delete;
00118     atomic_flag& operator=(const atomic_flag&) volatile = delete;
00119 
00120     // Conversion to ATOMIC_FLAG_INIT.
00121     atomic_flag(bool __i): __atomic_flag_base({ __i }) { }
00122 
00123     bool
00124     test_and_set(memory_order __m = memory_order_seq_cst);
00125 
00126     bool
00127     test_and_set(memory_order __m = memory_order_seq_cst) volatile;
00128 
00129     void
00130     clear(memory_order __m = memory_order_seq_cst);
00131 
00132     void
00133     clear(memory_order __m = memory_order_seq_cst) volatile;
00134   };
00135 
00136 
00137   /// atomic_address
00138   struct atomic_address
00139   {
00140   private:
00141     void* _M_i;
00142 
00143   public:
00144     atomic_address() = default;
00145     ~atomic_address() = default;
00146     atomic_address(const atomic_address&) = delete;
00147     atomic_address& operator=(const atomic_address&) = delete;
00148     atomic_address& operator=(const atomic_address&) volatile = delete;
00149 
00150     constexpr atomic_address(void* __v): _M_i (__v) { }
00151 
00152     bool
00153     is_lock_free() const { return false; }
00154 
00155     bool
00156     is_lock_free() const volatile { return false; }
00157 
00158     void
00159     store(void* __v, memory_order __m = memory_order_seq_cst)
00160     {
00161       __glibcxx_assert(__m != memory_order_acquire);
00162       __glibcxx_assert(__m != memory_order_acq_rel);
00163       __glibcxx_assert(__m != memory_order_consume);
00164       _ATOMIC_STORE_(this, __v, __m);
00165     }
00166 
00167     void
00168     store(void* __v, memory_order __m = memory_order_seq_cst) volatile
00169     {
00170       __glibcxx_assert(__m != memory_order_acquire);
00171       __glibcxx_assert(__m != memory_order_acq_rel);
00172       __glibcxx_assert(__m != memory_order_consume);
00173       _ATOMIC_STORE_(this, __v, __m);
00174     }
00175 
00176     void*
00177     load(memory_order __m = memory_order_seq_cst) const
00178     {
00179       __glibcxx_assert(__m != memory_order_release);
00180       __glibcxx_assert(__m != memory_order_acq_rel);
00181       return _ATOMIC_LOAD_(this, __m);
00182     }
00183 
00184     void*
00185     load(memory_order __m = memory_order_seq_cst) const volatile
00186     {
00187       __glibcxx_assert(__m != memory_order_release);
00188       __glibcxx_assert(__m != memory_order_acq_rel);
00189       return _ATOMIC_LOAD_(this, __m);
00190     }
00191 
00192     void*
00193     exchange(void* __v, memory_order __m = memory_order_seq_cst)
00194     { return _ATOMIC_MODIFY_(this, =, __v, __m); }
00195 
00196     void*
00197     exchange(void* __v, memory_order __m = memory_order_seq_cst) volatile
00198     { return _ATOMIC_MODIFY_(this, =, __v, __m); }
00199 
00200     bool
00201     compare_exchange_weak(void*& __v1, void* __v2, memory_order __m1,
00202               memory_order __m2)
00203     {
00204       __glibcxx_assert(__m2 != memory_order_release);
00205       __glibcxx_assert(__m2 != memory_order_acq_rel);
00206       __glibcxx_assert(__m2 <= __m1);
00207       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
00208     }
00209 
00210     bool
00211     compare_exchange_weak(void*& __v1, void* __v2, memory_order __m1,
00212               memory_order __m2) volatile
00213     {
00214       __glibcxx_assert(__m2 != memory_order_release);
00215       __glibcxx_assert(__m2 != memory_order_acq_rel);
00216       __glibcxx_assert(__m2 <= __m1);
00217       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
00218     }
00219 
00220     bool
00221     compare_exchange_weak(void*& __v1, void* __v2,
00222               memory_order __m = memory_order_seq_cst)
00223     {
00224       return compare_exchange_weak(__v1, __v2, __m,
00225                    __calculate_memory_order(__m));
00226     }
00227 
00228     bool
00229     compare_exchange_weak(void*& __v1, void* __v2,
00230               memory_order __m = memory_order_seq_cst) volatile
00231     {
00232       return compare_exchange_weak(__v1, __v2, __m,
00233                    __calculate_memory_order(__m));
00234     }
00235 
00236     bool
00237     compare_exchange_weak(const void*& __v1, const void* __v2,
00238               memory_order __m1, memory_order __m2)
00239     {
00240       __glibcxx_assert(__m2 != memory_order_release);
00241       __glibcxx_assert(__m2 != memory_order_acq_rel);
00242       __glibcxx_assert(__m2 <= __m1);
00243       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
00244     }
00245 
00246     bool
00247     compare_exchange_weak(const void*& __v1, const void* __v2,
00248               memory_order __m1, memory_order __m2) volatile
00249     {
00250       __glibcxx_assert(__m2 != memory_order_release);
00251       __glibcxx_assert(__m2 != memory_order_acq_rel);
00252       __glibcxx_assert(__m2 <= __m1);
00253       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
00254     }
00255 
00256     bool
00257     compare_exchange_weak(const void*& __v1, const void* __v2,
00258               memory_order __m = memory_order_seq_cst)
00259     {
00260       return compare_exchange_weak(__v1, __v2, __m,
00261                    __calculate_memory_order(__m));
00262     }
00263 
00264     bool
00265     compare_exchange_weak(const void*& __v1, const void* __v2,
00266               memory_order __m = memory_order_seq_cst) volatile
00267     {
00268       return compare_exchange_weak(__v1, __v2, __m,
00269                    __calculate_memory_order(__m));
00270     }
00271 
00272     bool
00273     compare_exchange_strong(void*& __v1, void* __v2, memory_order __m1,
00274                 memory_order __m2)
00275     {
00276       __glibcxx_assert(__m2 != memory_order_release);
00277       __glibcxx_assert(__m2 != memory_order_acq_rel);
00278       __glibcxx_assert(__m2 <= __m1);
00279       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
00280     }
00281 
00282     bool
00283     compare_exchange_strong(void*& __v1, void* __v2, memory_order __m1,
00284                 memory_order __m2) volatile
00285     {
00286       __glibcxx_assert(__m2 != memory_order_release);
00287       __glibcxx_assert(__m2 != memory_order_acq_rel);
00288       __glibcxx_assert(__m2 <= __m1);
00289       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
00290     }
00291 
00292     bool
00293     compare_exchange_strong(void*& __v1, void* __v2,
00294                 memory_order __m = memory_order_seq_cst)
00295     {
00296       return compare_exchange_strong(__v1, __v2, __m,
00297                      __calculate_memory_order(__m));
00298     }
00299 
00300     bool
00301     compare_exchange_strong(void*& __v1, void* __v2,
00302                 memory_order __m = memory_order_seq_cst) volatile
00303     {
00304       return compare_exchange_strong(__v1, __v2, __m,
00305                      __calculate_memory_order(__m));
00306     }
00307 
00308     bool
00309     compare_exchange_strong(const void*& __v1, const void* __v2,
00310                 memory_order __m1, memory_order __m2)
00311     {
00312       __glibcxx_assert(__m2 != memory_order_release);
00313       __glibcxx_assert(__m2 != memory_order_acq_rel);
00314       __glibcxx_assert(__m2 <= __m1);
00315       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
00316     }
00317 
00318     bool
00319     compare_exchange_strong(const void*& __v1, const void* __v2,
00320                 memory_order __m1, memory_order __m2) volatile
00321     {
00322       __glibcxx_assert(__m2 != memory_order_release);
00323       __glibcxx_assert(__m2 != memory_order_acq_rel);
00324       __glibcxx_assert(__m2 <= __m1);
00325       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
00326     }
00327 
00328     bool
00329     compare_exchange_strong(const void*& __v1, const void* __v2,
00330                 memory_order __m = memory_order_seq_cst)
00331     {
00332       return compare_exchange_strong(__v1, __v2, __m,
00333                      __calculate_memory_order(__m));
00334     }
00335 
00336     bool
00337     compare_exchange_strong(const void*& __v1, const void* __v2,
00338                 memory_order __m = memory_order_seq_cst) volatile
00339     {
00340       return compare_exchange_strong(__v1, __v2, __m,
00341                      __calculate_memory_order(__m));
00342     }
00343 
00344     void*
00345     fetch_add(ptrdiff_t __d, memory_order __m = memory_order_seq_cst)
00346     {
00347       void** __p = &(_M_i);
00348       __atomic_flag_base* __g = __atomic_flag_for_address(__p);
00349       __atomic_flag_wait_explicit(__g, __m);
00350       void* __r = *__p;
00351       *__p = (void*)((char*)(*__p) + __d);
00352       atomic_flag_clear_explicit(__g, __m);
00353       return __r;
00354     }
00355 
00356     void*
00357     fetch_add(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile
00358     {
00359       void* volatile* __p = &(_M_i);
00360       __atomic_flag_base* __g = __atomic_flag_for_address(__p);
00361       __atomic_flag_wait_explicit(__g, __m);
00362       void* __r = *__p;
00363       *__p = (void*)((char*)(*__p) + __d);
00364       atomic_flag_clear_explicit(__g, __m);
00365       return __r;
00366     }
00367 
00368     void*
00369     fetch_sub(ptrdiff_t __d, memory_order __m = memory_order_seq_cst)
00370     {
00371       void** __p = &(_M_i);
00372       __atomic_flag_base* __g = __atomic_flag_for_address(__p);
00373       __atomic_flag_wait_explicit(__g, __m);
00374       void* __r = *__p;
00375       *__p = (void*)((char*)(*__p) - __d);
00376       atomic_flag_clear_explicit(__g, __m);
00377       return __r;
00378     }
00379 
00380     void*
00381     fetch_sub(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile
00382     {
00383       void* volatile* __p = &(_M_i);
00384       __atomic_flag_base* __g = __atomic_flag_for_address(__p);
00385       __atomic_flag_wait_explicit(__g, __m);
00386       void* __r = *__p;
00387       *__p = (void*)((char*)(*__p) - __d);
00388       atomic_flag_clear_explicit(__g, __m);
00389       return __r;
00390     }
00391 
00392     operator void*() const
00393     { return load(); }
00394 
00395     operator void*() const volatile
00396     { return load(); }
00397 
00398     // XXX
00399     void*
00400     operator=(void* __v)
00401     {
00402       store(__v);
00403       return __v;
00404     }
00405 
00406     void*
00407     operator=(void* __v) volatile
00408     {
00409       store(__v);
00410       return __v;
00411     }
00412 
00413     void*
00414     operator+=(ptrdiff_t __d)
00415     { return fetch_add(__d) + __d; }
00416 
00417     void*
00418     operator+=(ptrdiff_t __d) volatile
00419     { return fetch_add(__d) + __d; }
00420 
00421     void*
00422     operator-=(ptrdiff_t __d)
00423     { return fetch_sub(__d) - __d; }
00424 
00425     void*
00426     operator-=(ptrdiff_t __d) volatile
00427     { return fetch_sub(__d) - __d; }
00428   };
00429 
00430 
00431   /// Base class for atomic integrals.
00432   //
00433   // For each of the integral types, define atomic_[integral type] struct
00434   //
00435   // atomic_bool     bool
00436   // atomic_char     char
00437   // atomic_schar    signed char
00438   // atomic_uchar    unsigned char
00439   // atomic_short    short
00440   // atomic_ushort   unsigned short
00441   // atomic_int      int
00442   // atomic_uint     unsigned int
00443   // atomic_long     long
00444   // atomic_ulong    unsigned long
00445   // atomic_llong    long long
00446   // atomic_ullong   unsigned long long
00447   // atomic_char16_t char16_t
00448   // atomic_char32_t char32_t
00449   // atomic_wchar_t  wchar_t
00450 
00451   // Base type.
00452   // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or 8 bytes,
00453   // since that is what GCC built-in functions for atomic memory access work on.
00454   template<typename _ITp>
00455     struct __atomic_base
00456     {
00457     private:
00458       typedef _ITp  __int_type;
00459 
00460       __int_type    _M_i;
00461 
00462     public:
00463       __atomic_base() = default;
00464       ~__atomic_base() = default;
00465       __atomic_base(const __atomic_base&) = delete;
00466       __atomic_base& operator=(const __atomic_base&) = delete;
00467       __atomic_base& operator=(const __atomic_base&) volatile = delete;
00468 
00469       // Requires __int_type convertible to _M_base._M_i.
00470       constexpr __atomic_base(__int_type __i): _M_i (__i) { }
00471 
00472       operator __int_type() const
00473       { return load(); }
00474 
00475       operator __int_type() const volatile
00476       { return load(); }
00477 
00478       __int_type
00479       operator=(__int_type __i)
00480       {
00481     store(__i);
00482     return __i;
00483       }
00484 
00485       __int_type
00486       operator=(__int_type __i) volatile
00487       {
00488     store(__i);
00489     return __i;
00490       }
00491 
00492       __int_type
00493       operator++(int)
00494       { return fetch_add(1); }
00495 
00496       __int_type
00497       operator++(int) volatile
00498       { return fetch_add(1); }
00499 
00500       __int_type
00501       operator--(int)
00502       { return fetch_sub(1); }
00503 
00504       __int_type
00505       operator--(int) volatile
00506       { return fetch_sub(1); }
00507 
00508       __int_type
00509       operator++()
00510       { return fetch_add(1) + 1; }
00511 
00512       __int_type
00513       operator++() volatile
00514       { return fetch_add(1) + 1; }
00515 
00516       __int_type
00517       operator--()
00518       { return fetch_sub(1) - 1; }
00519 
00520       __int_type
00521       operator--() volatile
00522       { return fetch_sub(1) - 1; }
00523 
00524       __int_type
00525       operator+=(__int_type __i)
00526       { return fetch_add(__i) + __i; }
00527 
00528       __int_type
00529       operator+=(__int_type __i) volatile
00530       { return fetch_add(__i) + __i; }
00531 
00532       __int_type
00533       operator-=(__int_type __i)
00534       { return fetch_sub(__i) - __i; }
00535 
00536       __int_type
00537       operator-=(__int_type __i) volatile
00538       { return fetch_sub(__i) - __i; }
00539 
00540       __int_type
00541       operator&=(__int_type __i)
00542       { return fetch_and(__i) & __i; }
00543 
00544       __int_type
00545       operator&=(__int_type __i) volatile
00546       { return fetch_and(__i) & __i; }
00547 
00548       __int_type
00549       operator|=(__int_type __i)
00550       { return fetch_or(__i) | __i; }
00551 
00552       __int_type
00553       operator|=(__int_type __i) volatile
00554       { return fetch_or(__i) | __i; }
00555 
00556       __int_type
00557       operator^=(__int_type __i)
00558       { return fetch_xor(__i) ^ __i; }
00559 
00560       __int_type
00561       operator^=(__int_type __i) volatile
00562       { return fetch_xor(__i) ^ __i; }
00563 
00564       bool
00565       is_lock_free() const
00566       { return false; }
00567 
00568       bool
00569       is_lock_free() const volatile
00570       { return false; }
00571 
00572       void
00573       store(__int_type __i, memory_order __m = memory_order_seq_cst)
00574       {
00575     __glibcxx_assert(__m != memory_order_acquire);
00576     __glibcxx_assert(__m != memory_order_acq_rel);
00577     __glibcxx_assert(__m != memory_order_consume);
00578     _ATOMIC_STORE_(this, __i, __m);
00579       }
00580 
00581       void
00582       store(__int_type __i, memory_order __m = memory_order_seq_cst) volatile
00583       {
00584     __glibcxx_assert(__m != memory_order_acquire);
00585     __glibcxx_assert(__m != memory_order_acq_rel);
00586     __glibcxx_assert(__m != memory_order_consume);
00587     _ATOMIC_STORE_(this, __i, __m);
00588       }
00589 
00590       __int_type
00591       load(memory_order __m = memory_order_seq_cst) const
00592       {
00593     __glibcxx_assert(__m != memory_order_release);
00594     __glibcxx_assert(__m != memory_order_acq_rel);
00595     return _ATOMIC_LOAD_(this, __m);
00596       }
00597 
00598       __int_type
00599       load(memory_order __m = memory_order_seq_cst) const volatile
00600       {
00601     __glibcxx_assert(__m != memory_order_release);
00602     __glibcxx_assert(__m != memory_order_acq_rel);
00603     return _ATOMIC_LOAD_(this, __m);
00604       }
00605 
00606       __int_type
00607       exchange(__int_type __i, memory_order __m = memory_order_seq_cst)
00608       { return _ATOMIC_MODIFY_(this, =, __i, __m); }
00609 
00610       __int_type
00611       exchange(__int_type __i, memory_order __m = memory_order_seq_cst) volatile
00612       { return _ATOMIC_MODIFY_(this, =, __i, __m); }
00613 
00614       bool
00615       compare_exchange_weak(__int_type& __i1, __int_type __i2,
00616                 memory_order __m1, memory_order __m2)
00617       {
00618     __glibcxx_assert(__m2 != memory_order_release);
00619     __glibcxx_assert(__m2 != memory_order_acq_rel);
00620     __glibcxx_assert(__m2 <= __m1);
00621     return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
00622       }
00623 
00624       bool
00625       compare_exchange_weak(__int_type& __i1, __int_type __i2,
00626                 memory_order __m1, memory_order __m2) volatile
00627       {
00628     __glibcxx_assert(__m2 != memory_order_release);
00629     __glibcxx_assert(__m2 != memory_order_acq_rel);
00630     __glibcxx_assert(__m2 <= __m1);
00631     return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
00632       }
00633 
00634       bool
00635       compare_exchange_weak(__int_type& __i1, __int_type __i2,
00636                 memory_order __m = memory_order_seq_cst)
00637       {
00638     return compare_exchange_weak(__i1, __i2, __m,
00639                      __calculate_memory_order(__m));
00640       }
00641 
00642       bool
00643       compare_exchange_weak(__int_type& __i1, __int_type __i2,
00644                 memory_order __m = memory_order_seq_cst) volatile
00645       {
00646     return compare_exchange_weak(__i1, __i2, __m,
00647                      __calculate_memory_order(__m));
00648       }
00649 
00650       bool
00651       compare_exchange_strong(__int_type& __i1, __int_type __i2,
00652                   memory_order __m1, memory_order __m2)
00653       {
00654     __glibcxx_assert(__m2 != memory_order_release);
00655     __glibcxx_assert(__m2 != memory_order_acq_rel);
00656     __glibcxx_assert(__m2 <= __m1);
00657     return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
00658       }
00659 
00660       bool
00661       compare_exchange_strong(__int_type& __i1, __int_type __i2,
00662                   memory_order __m1, memory_order __m2) volatile
00663       {
00664     __glibcxx_assert(__m2 != memory_order_release);
00665     __glibcxx_assert(__m2 != memory_order_acq_rel);
00666     __glibcxx_assert(__m2 <= __m1);
00667     return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
00668       }
00669 
00670       bool
00671       compare_exchange_strong(__int_type& __i1, __int_type __i2,
00672                   memory_order __m = memory_order_seq_cst)
00673       {
00674     return compare_exchange_strong(__i1, __i2, __m,
00675                        __calculate_memory_order(__m));
00676       }
00677 
00678       bool
00679       compare_exchange_strong(__int_type& __i1, __int_type __i2,
00680                   memory_order __m = memory_order_seq_cst) volatile
00681       {
00682     return compare_exchange_strong(__i1, __i2, __m,
00683                        __calculate_memory_order(__m));
00684       }
00685 
00686       __int_type
00687       fetch_add(__int_type __i, memory_order __m = memory_order_seq_cst)
00688       { return _ATOMIC_MODIFY_(this, +=, __i, __m); }
00689 
00690       __int_type
00691       fetch_add(__int_type __i,
00692         memory_order __m = memory_order_seq_cst) volatile
00693       { return _ATOMIC_MODIFY_(this, +=, __i, __m); }
00694 
00695       __int_type
00696       fetch_sub(__int_type __i, memory_order __m = memory_order_seq_cst)
00697       { return _ATOMIC_MODIFY_(this, -=, __i, __m); }
00698 
00699       __int_type
00700       fetch_sub(__int_type __i,
00701         memory_order __m = memory_order_seq_cst) volatile
00702       { return _ATOMIC_MODIFY_(this, -=, __i, __m); }
00703 
00704       __int_type
00705       fetch_and(__int_type __i, memory_order __m = memory_order_seq_cst)
00706       { return _ATOMIC_MODIFY_(this, &=, __i, __m); }
00707 
00708       __int_type
00709       fetch_and(__int_type __i,
00710         memory_order __m = memory_order_seq_cst) volatile
00711       { return _ATOMIC_MODIFY_(this, &=, __i, __m); }
00712 
00713       __int_type
00714       fetch_or(__int_type __i, memory_order __m = memory_order_seq_cst)
00715       { return _ATOMIC_MODIFY_(this, |=, __i, __m); }
00716 
00717       __int_type
00718       fetch_or(__int_type __i, memory_order __m = memory_order_seq_cst) volatile
00719       { return _ATOMIC_MODIFY_(this, |=, __i, __m); }
00720 
00721       __int_type
00722       fetch_xor(__int_type __i, memory_order __m = memory_order_seq_cst)
00723       { return _ATOMIC_MODIFY_(this, ^=, __i, __m); }
00724 
00725       __int_type
00726       fetch_xor(__int_type __i,
00727         memory_order __m = memory_order_seq_cst) volatile
00728       { return _ATOMIC_MODIFY_(this, ^=, __i, __m); }
00729     };
00730 
00731 #undef _ATOMIC_LOAD_
00732 #undef _ATOMIC_STORE_
00733 #undef _ATOMIC_MODIFY_
00734 #undef _ATOMIC_CMPEXCHNG_
00735 } // namespace __atomic0
00736 
00737 _GLIBCXX_END_NAMESPACE_VERSION
00738 } // namespace
00739 
00740 #endif