# atomic_0.h

Go to the documentation of this file.

    00001 // -*- C++ -*- header.
    00002
    00003 // Copyright (C) 2008, 2009
    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  *  You should not attempt to use it directly.
    00029  */
    00030
    00031 #ifndef _GLIBCXX_ATOMIC_0_H
    00032 #define _GLIBCXX_ATOMIC_0_H 1
    00033
    00034 #pragma GCC system_header
    00035
    00036 // _GLIBCXX_BEGIN_NAMESPACE(std)
    00037
    00038   // 0 == __atomic0 == Never lock-free
    00039 namespace __atomic0
    00040 {
    00041   struct atomic_flag;
    00042
    00043   // Implementation specific defines.
    00044 #define _ATOMIC_LOAD_(__a, __x)                        \
    00045   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;      \
    00046     volatile __atomic_flag_base* __g = __atomic_flag_for_address(__p);     \
    00047     __atomic_flag_wait_explicit(__g, __x);                 \
    00048     __typeof__ _ATOMIC_MEMBER_ __r = *__p;                 \
    00049     atomic_flag_clear_explicit(__g, __x);                      \
    00050     __r; })
    00051
    00052 #define _ATOMIC_STORE_(__a, __m, __x)                      \
    00053   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;      \
    00054     __typeof__(__m) __v = (__m);                           \
    00055     volatile __atomic_flag_base* __g = __atomic_flag_for_address(__p);     \
    00056     __atomic_flag_wait_explicit(__g, __x);                 \
    00057     *__p = __v;                                \
    00058     atomic_flag_clear_explicit(__g, __x);                      \
    00059     __v; })
    00060
    00061 #define _ATOMIC_MODIFY_(__a, __o, __m, __x)                \
    00062   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;      \
    00063     __typeof__(__m) __v = (__m);                           \
    00064     volatile __atomic_flag_base* __g = __atomic_flag_for_address(__p);     \
    00065     __atomic_flag_wait_explicit(__g, __x);                 \
    00066     __typeof__ _ATOMIC_MEMBER_ __r = *__p;                 \
    00067     *__p __o __v;                                  \
    00068     atomic_flag_clear_explicit(__g, __x);                      \
    00069     __r; })
    00070
    00071 #define _ATOMIC_CMPEXCHNG_(__a, __e, __m, __x)                 \
    00072   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;      \
    00073     __typeof__(__e) __q = (__e);                           \
    00074     __typeof__(__m) __v = (__m);                           \
    00075     bool __r;                                      \
    00076     volatile __atomic_flag_base* __g = __atomic_flag_for_address(__p);     \
    00077     __atomic_flag_wait_explicit(__g, __x);                 \
    00078     __typeof__ _ATOMIC_MEMBER_ __t__ = *__p;                       \
    00079     if (__t__ == *__q) { *__p = __v; __r = true; }             \
    00080     else { *__q = __t__; __r = false; }                        \
    00081     atomic_flag_clear_explicit(__g, __x);                      \
    00082     __r; })
    00083
    00084   /// atomic_flag
    00085   struct atomic_flag : private __atomic_flag_base
    00086   {
    00087     atomic_flag() = default;
    00088     ~atomic_flag() = default;
    00089     atomic_flag(const atomic_flag&) = delete;
    00090     atomic_flag& operator=(const atomic_flag&) = delete;
    00091
    00092     atomic_flag(bool __i) { _M_i = __i; } // XXX deleted copy ctor != agg
    00093
    00094     bool
    00095     test_and_set(memory_order __m = memory_order_seq_cst) volatile;
    00096
    00097     void
    00098     clear(memory_order __m = memory_order_seq_cst) volatile;
    00099   };
    00100
    00101   /// 29.4.2, address types
    00102   struct atomic_address
    00103   {
    00104   private:
    00105     void* _M_i;
    00106
    00107   public:
    00108     atomic_address() = default;
    00109     ~atomic_address() = default;
    00110     atomic_address(const atomic_address&) = delete;
    00111     atomic_address& operator=(const atomic_address&) = delete;
    00112
    00113     atomic_address(void* __v) { _M_i = __v; }
    00114
    00115     bool
    00116     is_lock_free() const volatile
    00117     { return false; }
    00118
    00119     void
    00120     store(void* __v, memory_order __m = memory_order_seq_cst) volatile
    00121     {
    00122       __glibcxx_assert(__m == memory_order_acquire);
    00123       __glibcxx_assert(__m == memory_order_acq_rel);
    00124       __glibcxx_assert(__m == memory_order_consume);
    00125       _ATOMIC_STORE_(this, __v, __m);
    00126     }
    00127
    00128     void*
    00129     load(memory_order __m = memory_order_seq_cst) const volatile
    00130     {
    00131       __glibcxx_assert(__m == memory_order_release);
    00132       __glibcxx_assert(__m == memory_order_acq_rel);
    00133       return _ATOMIC_LOAD_(this, __m);
    00134     }
    00135
    00136     void*
    00137     exchange(void* __v, memory_order __m = memory_order_seq_cst) volatile
    00138     { return _ATOMIC_MODIFY_(this, =, __v, __m); }
    00139
    00140     bool
    00141     compare_exchange_weak(void*& __v1, void* __v2, memory_order __m1,
    00142               memory_order __m2) volatile
    00143     {
    00144       __glibcxx_assert(__m2 == memory_order_release);
    00145       __glibcxx_assert(__m2 == memory_order_acq_rel);
    00146       __glibcxx_assert(__m2 <= __m1);
    00147       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
    00148     }
    00149
    00150     bool
    00151     compare_exchange_weak(void*& __v1, void* __v2,
    00152               memory_order __m = memory_order_seq_cst) volatile
    00153     {
    00154       return compare_exchange_weak(__v1, __v2, __m,
    00155                    __calculate_memory_order(__m));
    00156     }
    00157
    00158     bool
    00159     compare_exchange_strong(void*& __v1, void* __v2, memory_order __m1,
    00160                 memory_order __m2) volatile
    00161     {
    00162       __glibcxx_assert(__m2 == memory_order_release);
    00163       __glibcxx_assert(__m2 == memory_order_acq_rel);
    00164       __glibcxx_assert(__m2 <= __m1);
    00165       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
    00166     }
    00167
    00168     bool
    00169     compare_exchange_strong(void*& __v1, void* __v2,
    00170               memory_order __m = memory_order_seq_cst) volatile
    00171     {
    00172       return compare_exchange_strong(__v1, __v2, __m,
    00173                      __calculate_memory_order(__m));
    00174     }
    00175
    00176     void*
    00177     fetch_add(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile
    00178     {
    00179       void* volatile* __p = &(_M_i);
    00180       volatile __atomic_flag_base* __g = __atomic_flag_for_address(__p);
    00181       __atomic_flag_wait_explicit(__g, __m);
    00182       void* __r = *__p;
    00183       *__p = (void*)((char*)(*__p) + __d);
    00184       atomic_flag_clear_explicit(__g, __m);
    00185       return __r;
    00186     }
    00187
    00188     void*
    00189     fetch_sub(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile
    00190     {
    00191       void* volatile* __p = &(_M_i);
    00192       volatile __atomic_flag_base* __g = __atomic_flag_for_address(__p);
    00193       __atomic_flag_wait_explicit(__g, __m);
    00194       void* __r = *__p;
    00195       *__p = (void*)((char*)(*__p) - __d);
    00196       atomic_flag_clear_explicit(__g, __m);
    00197       return __r;
    00198     }
    00199
    00200     operator void*() const volatile
    00201     { return load(); }
    00202
    00203     void*
    00204     operator=(void* __v) // XXX volatile
    00205     {
    00206       store(__v);
    00207       return __v;
    00208     }
    00209
    00210     void*
    00211     operator+=(ptrdiff_t __d) volatile
    00212     { return fetch_add(__d) + __d; }
    00213
    00214     void*
    00215     operator-=(ptrdiff_t __d) volatile
    00216     { return fetch_sub(__d) - __d; }
    00217   };
    00218
    00219
    00220   // 29.3.1 atomic integral types
    00221   // For each of the integral types, define atomic_[integral type] struct
    00222   //
    00223   // atomic_bool     bool
    00224   // atomic_char     char
    00225   // atomic_schar    signed char
    00226   // atomic_uchar    unsigned char
    00227   // atomic_short    short
    00228   // atomic_ushort   unsigned short
    00229   // atomic_int      int
    00230   // atomic_uint     unsigned int
    00231   // atomic_long     long
    00232   // atomic_ulong    unsigned long
    00233   // atomic_llong    long long
    00234   // atomic_ullong   unsigned long long
    00235   // atomic_char16_t char16_t
    00236   // atomic_char32_t char32_t
    00237   // atomic_wchar_t  wchar_t
    00238
    00239   // Base type.
    00240   // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or 8 bytes,
    00241   // since that is what GCC built-in functions for atomic memory access work on.
    00242   template<typename _ITp>
    00243     struct __atomic_base
    00244     {
    00245     private:
    00246       typedef _ITp  __integral_type;
    00247
    00248       __integral_type   _M_i;
    00249
    00250     public:
    00251       __atomic_base() = default;
    00252       ~__atomic_base() = default;
    00253       __atomic_base(const __atomic_base&) = delete;
    00254       __atomic_base& operator=(const __atomic_base&) = delete;
    00255
    00256       // Requires __integral_type convertible to _M_base._M_i.
    00257       __atomic_base(__integral_type __i) { _M_i = __i; }
    00258
    00259       operator __integral_type() const volatile
    00260       { return load(); }
    00261
    00262       __integral_type
    00263       operator=(__integral_type __i) // XXX volatile
    00264       {
    00265     store(__i);
    00266     return __i;
    00267       }
    00268
    00269       __integral_type
    00270       operator++(int) volatile
    00271       { return fetch_add(1); }
    00272
    00273       __integral_type
    00274       operator--(int) volatile
    00275       { return fetch_sub(1); }
    00276
    00277       __integral_type
    00278       operator++() volatile
    00279       { return fetch_add(1) + 1; }
    00280
    00281       __integral_type
    00282       operator--() volatile
    00283       { return fetch_sub(1) - 1; }
    00284
    00285       __integral_type
    00286       operator+=(__integral_type __i) volatile
    00287       { return fetch_add(__i) + __i; }
    00288
    00289       __integral_type
    00290       operator-=(__integral_type __i) volatile
    00291       { return fetch_sub(__i) - __i; }
    00292
    00293       __integral_type
    00294       operator&=(__integral_type __i) volatile
    00295       { return fetch_and(__i) & __i; }
    00296
    00297       __integral_type
    00298       operator|=(__integral_type __i) volatile
    00299       { return fetch_or(__i) | __i; }
    00300
    00301       __integral_type
    00302       operator^=(__integral_type __i) volatile
    00303       { return fetch_xor(__i) ^ __i; }
    00304
    00305       bool
    00306       is_lock_free() const volatile
    00307       { return false; }
    00308
    00309       void
    00310       store(__integral_type __i,
    00311         memory_order __m = memory_order_seq_cst) volatile
    00312       {
    00313     __glibcxx_assert(__m == memory_order_acquire);
    00314     __glibcxx_assert(__m == memory_order_acq_rel);
    00315     __glibcxx_assert(__m == memory_order_consume);
    00316     _ATOMIC_STORE_(this, __i, __m);
    00317       }
    00318
    00319       __integral_type
    00320       load(memory_order __m = memory_order_seq_cst) const volatile
    00321       {
    00322     __glibcxx_assert(__m == memory_order_release);
    00323     __glibcxx_assert(__m == memory_order_acq_rel);
    00324     return _ATOMIC_LOAD_(this, __m);
    00325       }
    00326
    00327       __integral_type
    00328       exchange(__integral_type __i,
    00329            memory_order __m = memory_order_seq_cst) volatile
    00330       { return _ATOMIC_MODIFY_(this, =, __i, __m); }
    00331
    00332       bool
    00333       compare_exchange_weak(__integral_type& __i1, __integral_type __i2,
    00334                 memory_order __m1, memory_order __m2) volatile
    00335       {
    00336     __glibcxx_assert(__m2 == memory_order_release);
    00337     __glibcxx_assert(__m2 == memory_order_acq_rel);
    00338     __glibcxx_assert(__m2 <= __m1);
    00339     return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
    00340       }
    00341
    00342       bool
    00343       compare_exchange_weak(__integral_type& __i1, __integral_type __i2,
    00344                 memory_order __m = memory_order_seq_cst) volatile
    00345       {
    00346     return compare_exchange_weak(__i1, __i2, __m,
    00347                      __calculate_memory_order(__m));
    00348       }
    00349
    00350       bool
    00351       compare_exchange_strong(__integral_type& __i1, __integral_type __i2,
    00352                   memory_order __m1, memory_order __m2) volatile
    00353       {
    00354     __glibcxx_assert(__m2 == memory_order_release);
    00355     __glibcxx_assert(__m2 == memory_order_acq_rel);
    00356     __glibcxx_assert(__m2 <= __m1);
    00357     return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
    00358       }
    00359
    00360       bool
    00361       compare_exchange_strong(__integral_type& __i1, __integral_type __i2,
    00362                   memory_order __m = memory_order_seq_cst) volatile
    00363       {
    00364     return compare_exchange_strong(__i1, __i2, __m,
    00365                        __calculate_memory_order(__m));
    00366       }
    00367
    00368       __integral_type
    00369       fetch_add(__integral_type __i,
    00370         memory_order __m = memory_order_seq_cst) volatile
    00371       { return _ATOMIC_MODIFY_(this, +=, __i, __m); }
    00372
    00373       __integral_type
    00374       fetch_sub(__integral_type __i,
    00375         memory_order __m = memory_order_seq_cst) volatile
    00376       { return _ATOMIC_MODIFY_(this, -=, __i, __m); }
    00377
    00378       __integral_type
    00379       fetch_and(__integral_type __i,
    00380         memory_order __m = memory_order_seq_cst) volatile
    00381       { return _ATOMIC_MODIFY_(this, &=, __i, __m); }
    00382
    00383       __integral_type
    00384       fetch_or(__integral_type __i,
    00385            memory_order __m = memory_order_seq_cst) volatile
    00386       { return _ATOMIC_MODIFY_(this, |=, __i, __m); }
    00387
    00388       __integral_type
    00389       fetch_xor(__integral_type __i,
    00390         memory_order __m = memory_order_seq_cst) volatile
    00391       { return _ATOMIC_MODIFY_(this, ^=, __i, __m); }
    00392     };
    00393
    00394
    00395   /// atomic_bool
    00396   // NB: No operators or fetch-operations for this type.
    00397   struct atomic_bool
    00398   {
    00399   private:
    00400     __atomic_base<bool> _M_base;
    00401
    00402   public:
    00403     atomic_bool() = default;
    00404     ~atomic_bool() = default;
    00405     atomic_bool(const atomic_bool&) = delete;
    00406     atomic_bool& operator=(const atomic_bool&) = delete;
    00407
    00408     atomic_bool(bool __i) : _M_base(__i) { }
    00409
    00410     bool
    00411     operator=(bool __i) // XXX volatile
    00412     { return _M_base.operator=(__i); }
    00413
    00414     operator bool() const volatile
    00415     { return _M_base.load(); }
    00416
    00417     bool
    00418     is_lock_free() const volatile
    00419     { return _M_base.is_lock_free(); }
    00420
    00421     void
    00422     store(bool __i, memory_order __m = memory_order_seq_cst) volatile
    00423     { _M_base.store(__i, __m); }
    00424
    00425     bool
    00426     load(memory_order __m = memory_order_seq_cst) const volatile
    00427     { return _M_base.load(__m); }
    00428
    00429     bool
    00430     exchange(bool __i, memory_order __m = memory_order_seq_cst) volatile
    00431     { return _M_base.exchange(__i, __m); }
    00432
    00433     bool
    00434     compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1,
    00435               memory_order __m2) volatile
    00436     { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); }
    00437
    00438     bool
    00439     compare_exchange_weak(bool& __i1, bool __i2,
    00440               memory_order __m = memory_order_seq_cst) volatile
    00441     { return _M_base.compare_exchange_weak(__i1, __i2, __m); }
    00442
    00443     bool
    00444     compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1,
    00445                 memory_order __m2) volatile
    00446     { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); }
    00447
    00448
    00449     bool
    00450     compare_exchange_strong(bool& __i1, bool __i2,
    00451                 memory_order __m = memory_order_seq_cst) volatile
    00452     { return _M_base.compare_exchange_strong(__i1, __i2, __m); }
    00453   };
    00454
    00455 #undef _ATOMIC_LOAD_
    00456 #undef _ATOMIC_STORE_
    00457 #undef _ATOMIC_MODIFY_
    00458 #undef _ATOMIC_CMPEXCHNG_
    00459 } // namespace __atomic0
    00460
    00461 // _GLIBCXX_END_NAMESPACE
    00462
    00463 #endif