Home | History | Annotate | Download | only in bits
      1 // -*- C++ -*- header.
      2 
      3 // Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file bits/atomic_base.h
     26  *  This is an internal header file, included by other library headers.
     27  *  Do not attempt to use it directly. @headername{atomic}
     28  */
     29 
     30 #ifndef _GLIBCXX_ATOMIC_BASE_H
     31 #define _GLIBCXX_ATOMIC_BASE_H 1
     32 
     33 #pragma GCC system_header
     34 
     35 #include <bits/c++config.h>
     36 #include <stdbool.h>
     37 #include <stdint.h>
     38 #include <bits/atomic_lockfree_defines.h>
     39 
     40 namespace std _GLIBCXX_VISIBILITY(default)
     41 {
     42 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     43 
     44   /**
     45    * @defgroup atomics Atomics
     46    *
     47    * Components for performing atomic operations.
     48    * @{
     49    */
     50 
     51   /// Enumeration for memory_order
     52   typedef enum memory_order
     53     {
     54       memory_order_relaxed,
     55       memory_order_consume,
     56       memory_order_acquire,
     57       memory_order_release,
     58       memory_order_acq_rel,
     59       memory_order_seq_cst
     60     } memory_order;
     61 
     62   // Drop release ordering as per [atomics.types.operations.req]/21
     63   constexpr memory_order
     64   __cmpexch_failure_order(memory_order __m) noexcept
     65   {
     66     return __m == memory_order_acq_rel ? memory_order_acquire
     67       : __m == memory_order_release ? memory_order_relaxed : __m;
     68   }
     69 
     70   inline void
     71   atomic_thread_fence(memory_order __m) noexcept
     72   { __atomic_thread_fence(__m); }
     73 
     74   inline void
     75   atomic_signal_fence(memory_order __m) noexcept
     76   { __atomic_thread_fence(__m); }
     77 
     78   /// kill_dependency
     79   template<typename _Tp>
     80     inline _Tp
     81     kill_dependency(_Tp __y) noexcept
     82     {
     83       _Tp __ret(__y);
     84       return __ret;
     85     }
     86 
     87 
     88   // Base types for atomics.
     89   template<typename _IntTp>
     90     struct __atomic_base;
     91 
     92   /// atomic_char
     93   typedef __atomic_base<char>  	       		atomic_char;
     94 
     95   /// atomic_schar
     96   typedef __atomic_base<signed char>	     	atomic_schar;
     97 
     98   /// atomic_uchar
     99   typedef __atomic_base<unsigned char>		atomic_uchar;
    100 
    101   /// atomic_short
    102   typedef __atomic_base<short>			atomic_short;
    103 
    104   /// atomic_ushort
    105   typedef __atomic_base<unsigned short>	 	atomic_ushort;
    106 
    107   /// atomic_int
    108   typedef __atomic_base<int>  	       		atomic_int;
    109 
    110   /// atomic_uint
    111   typedef __atomic_base<unsigned int>	     	atomic_uint;
    112 
    113   /// atomic_long
    114   typedef __atomic_base<long>  	       		atomic_long;
    115 
    116   /// atomic_ulong
    117   typedef __atomic_base<unsigned long>		atomic_ulong;
    118 
    119   /// atomic_llong
    120   typedef __atomic_base<long long>  		atomic_llong;
    121 
    122   /// atomic_ullong
    123   typedef __atomic_base<unsigned long long> 	atomic_ullong;
    124 
    125   /// atomic_wchar_t
    126   typedef __atomic_base<wchar_t>  		atomic_wchar_t;
    127 
    128   /// atomic_char16_t
    129   typedef __atomic_base<char16_t>  		atomic_char16_t;
    130 
    131   /// atomic_char32_t
    132   typedef __atomic_base<char32_t>  		atomic_char32_t;
    133 
    134   /// atomic_char32_t
    135   typedef __atomic_base<char32_t>  		atomic_char32_t;
    136 
    137 
    138   /// atomic_int_least8_t
    139   typedef __atomic_base<int_least8_t>  		atomic_int_least8_t;
    140 
    141   /// atomic_uint_least8_t
    142   typedef __atomic_base<uint_least8_t>	       	atomic_uint_least8_t;
    143 
    144   /// atomic_int_least16_t
    145   typedef __atomic_base<int_least16_t>	       	atomic_int_least16_t;
    146 
    147   /// atomic_uint_least16_t
    148   typedef __atomic_base<uint_least16_t>	       	atomic_uint_least16_t;
    149 
    150   /// atomic_int_least32_t
    151   typedef __atomic_base<int_least32_t>	       	atomic_int_least32_t;
    152 
    153   /// atomic_uint_least32_t
    154   typedef __atomic_base<uint_least32_t>	       	atomic_uint_least32_t;
    155 
    156   /// atomic_int_least64_t
    157   typedef __atomic_base<int_least64_t>	       	atomic_int_least64_t;
    158 
    159   /// atomic_uint_least64_t
    160   typedef __atomic_base<uint_least64_t>	       	atomic_uint_least64_t;
    161 
    162 
    163   /// atomic_int_fast8_t
    164   typedef __atomic_base<int_fast8_t>  		atomic_int_fast8_t;
    165 
    166   /// atomic_uint_fast8_t
    167   typedef __atomic_base<uint_fast8_t>	      	atomic_uint_fast8_t;
    168 
    169   /// atomic_int_fast16_t
    170   typedef __atomic_base<int_fast16_t>	      	atomic_int_fast16_t;
    171 
    172   /// atomic_uint_fast16_t
    173   typedef __atomic_base<uint_fast16_t>	      	atomic_uint_fast16_t;
    174 
    175   /// atomic_int_fast32_t
    176   typedef __atomic_base<int_fast32_t>	      	atomic_int_fast32_t;
    177 
    178   /// atomic_uint_fast32_t
    179   typedef __atomic_base<uint_fast32_t>	      	atomic_uint_fast32_t;
    180 
    181   /// atomic_int_fast64_t
    182   typedef __atomic_base<int_fast64_t>	      	atomic_int_fast64_t;
    183 
    184   /// atomic_uint_fast64_t
    185   typedef __atomic_base<uint_fast64_t>	      	atomic_uint_fast64_t;
    186 
    187 
    188   /// atomic_intptr_t
    189   typedef __atomic_base<intptr_t>  	       	atomic_intptr_t;
    190 
    191   /// atomic_uintptr_t
    192   typedef __atomic_base<uintptr_t>  	       	atomic_uintptr_t;
    193 
    194   /// atomic_size_t
    195   typedef __atomic_base<size_t>	 	       	atomic_size_t;
    196 
    197   /// atomic_intmax_t
    198   typedef __atomic_base<intmax_t>  	       	atomic_intmax_t;
    199 
    200   /// atomic_uintmax_t
    201   typedef __atomic_base<uintmax_t>  	       	atomic_uintmax_t;
    202 
    203   /// atomic_ptrdiff_t
    204   typedef __atomic_base<ptrdiff_t>  	       	atomic_ptrdiff_t;
    205 
    206 
    207 #define ATOMIC_VAR_INIT(_VI) { _VI }
    208 
    209   template<typename _Tp>
    210     struct atomic;
    211 
    212   template<typename _Tp>
    213     struct atomic<_Tp*>;
    214 
    215 
    216   /**
    217    *  @brief Base type for atomic_flag.
    218    *
    219    *  Base type is POD with data, allowing atomic_flag to derive from
    220    *  it and meet the standard layout type requirement. In addition to
    221    *  compatibilty with a C interface, this allows different
    222    *  implementations of atomic_flag to use the same atomic operation
    223    *  functions, via a standard conversion to the __atomic_flag_base
    224    *  argument.
    225   */
    226   _GLIBCXX_BEGIN_EXTERN_C
    227 
    228   struct __atomic_flag_base
    229   {
    230     /* The target's "set" value for test-and-set may not be exactly 1.  */
    231 #if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1
    232     bool _M_i;
    233 #else
    234     unsigned char _M_i;
    235 #endif
    236   };
    237 
    238   _GLIBCXX_END_EXTERN_C
    239 
    240 #define ATOMIC_FLAG_INIT { 0 }
    241 
    242   /// atomic_flag
    243   struct atomic_flag : public __atomic_flag_base
    244   {
    245     atomic_flag() noexcept = default;
    246     ~atomic_flag() noexcept = default;
    247     atomic_flag(const atomic_flag&) = delete;
    248     atomic_flag& operator=(const atomic_flag&) = delete;
    249     atomic_flag& operator=(const atomic_flag&) volatile = delete;
    250 
    251     // Conversion to ATOMIC_FLAG_INIT.
    252     constexpr atomic_flag(bool __i) noexcept
    253       : __atomic_flag_base({ __i ? __GCC_ATOMIC_TEST_AND_SET_TRUEVAL : 0 })
    254     { }
    255 
    256     bool
    257     test_and_set(memory_order __m = memory_order_seq_cst) noexcept
    258     {
    259       return __atomic_test_and_set (&_M_i, __m);
    260     }
    261 
    262     bool
    263     test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept
    264     {
    265       return __atomic_test_and_set (&_M_i, __m);
    266     }
    267 
    268     void
    269     clear(memory_order __m = memory_order_seq_cst) noexcept
    270     {
    271       __glibcxx_assert(__m != memory_order_consume);
    272       __glibcxx_assert(__m != memory_order_acquire);
    273       __glibcxx_assert(__m != memory_order_acq_rel);
    274 
    275       __atomic_clear (&_M_i, __m);
    276     }
    277 
    278     void
    279     clear(memory_order __m = memory_order_seq_cst) volatile noexcept
    280     {
    281       __glibcxx_assert(__m != memory_order_consume);
    282       __glibcxx_assert(__m != memory_order_acquire);
    283       __glibcxx_assert(__m != memory_order_acq_rel);
    284 
    285       __atomic_clear (&_M_i, __m);
    286     }
    287   };
    288 
    289 
    290   /// Base class for atomic integrals.
    291   //
    292   // For each of the integral types, define atomic_[integral type] struct
    293   //
    294   // atomic_bool     bool
    295   // atomic_char     char
    296   // atomic_schar    signed char
    297   // atomic_uchar    unsigned char
    298   // atomic_short    short
    299   // atomic_ushort   unsigned short
    300   // atomic_int      int
    301   // atomic_uint     unsigned int
    302   // atomic_long     long
    303   // atomic_ulong    unsigned long
    304   // atomic_llong    long long
    305   // atomic_ullong   unsigned long long
    306   // atomic_char16_t char16_t
    307   // atomic_char32_t char32_t
    308   // atomic_wchar_t  wchar_t
    309   //
    310   // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or
    311   // 8 bytes, since that is what GCC built-in functions for atomic
    312   // memory access expect.
    313   template<typename _ITp>
    314     struct __atomic_base
    315     {
    316     private:
    317       typedef _ITp 	__int_type;
    318 
    319       __int_type 	_M_i;
    320 
    321     public:
    322       __atomic_base() noexcept = default;
    323       ~__atomic_base() noexcept = default;
    324       __atomic_base(const __atomic_base&) = delete;
    325       __atomic_base& operator=(const __atomic_base&) = delete;
    326       __atomic_base& operator=(const __atomic_base&) volatile = delete;
    327 
    328       // Requires __int_type convertible to _M_i.
    329       constexpr __atomic_base(__int_type __i) noexcept : _M_i (__i) { }
    330 
    331       operator __int_type() const noexcept
    332       { return load(); }
    333 
    334       operator __int_type() const volatile noexcept
    335       { return load(); }
    336 
    337       __int_type
    338       operator=(__int_type __i) noexcept
    339       {
    340 	store(__i);
    341 	return __i;
    342       }
    343 
    344       __int_type
    345       operator=(__int_type __i) volatile noexcept
    346       {
    347 	store(__i);
    348 	return __i;
    349       }
    350 
    351       __int_type
    352       operator++(int) noexcept
    353       { return fetch_add(1); }
    354 
    355       __int_type
    356       operator++(int) volatile noexcept
    357       { return fetch_add(1); }
    358 
    359       __int_type
    360       operator--(int) noexcept
    361       { return fetch_sub(1); }
    362 
    363       __int_type
    364       operator--(int) volatile noexcept
    365       { return fetch_sub(1); }
    366 
    367       __int_type
    368       operator++() noexcept
    369       { return __atomic_add_fetch(&_M_i, 1, memory_order_seq_cst); }
    370 
    371       __int_type
    372       operator++() volatile noexcept
    373       { return __atomic_add_fetch(&_M_i, 1, memory_order_seq_cst); }
    374 
    375       __int_type
    376       operator--() noexcept
    377       { return __atomic_sub_fetch(&_M_i, 1, memory_order_seq_cst); }
    378 
    379       __int_type
    380       operator--() volatile noexcept
    381       { return __atomic_sub_fetch(&_M_i, 1, memory_order_seq_cst); }
    382 
    383       __int_type
    384       operator+=(__int_type __i) noexcept
    385       { return __atomic_add_fetch(&_M_i, __i, memory_order_seq_cst); }
    386 
    387       __int_type
    388       operator+=(__int_type __i) volatile noexcept
    389       { return __atomic_add_fetch(&_M_i, __i, memory_order_seq_cst); }
    390 
    391       __int_type
    392       operator-=(__int_type __i) noexcept
    393       { return __atomic_sub_fetch(&_M_i, __i, memory_order_seq_cst); }
    394 
    395       __int_type
    396       operator-=(__int_type __i) volatile noexcept
    397       { return __atomic_sub_fetch(&_M_i, __i, memory_order_seq_cst); }
    398 
    399       __int_type
    400       operator&=(__int_type __i) noexcept
    401       { return __atomic_and_fetch(&_M_i, __i, memory_order_seq_cst); }
    402 
    403       __int_type
    404       operator&=(__int_type __i) volatile noexcept
    405       { return __atomic_and_fetch(&_M_i, __i, memory_order_seq_cst); }
    406 
    407       __int_type
    408       operator|=(__int_type __i) noexcept
    409       { return __atomic_or_fetch(&_M_i, __i, memory_order_seq_cst); }
    410 
    411       __int_type
    412       operator|=(__int_type __i) volatile noexcept
    413       { return __atomic_or_fetch(&_M_i, __i, memory_order_seq_cst); }
    414 
    415       __int_type
    416       operator^=(__int_type __i) noexcept
    417       { return __atomic_xor_fetch(&_M_i, __i, memory_order_seq_cst); }
    418 
    419       __int_type
    420       operator^=(__int_type __i) volatile noexcept
    421       { return __atomic_xor_fetch(&_M_i, __i, memory_order_seq_cst); }
    422 
    423       bool
    424       is_lock_free() const noexcept
    425       { return __atomic_is_lock_free (sizeof (_M_i), &_M_i); }
    426 
    427       bool
    428       is_lock_free() const volatile noexcept
    429       { return __atomic_is_lock_free (sizeof (_M_i), &_M_i); }
    430 
    431       void
    432       store(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept
    433       {
    434 	__glibcxx_assert(__m != memory_order_acquire);
    435 	__glibcxx_assert(__m != memory_order_acq_rel);
    436 	__glibcxx_assert(__m != memory_order_consume);
    437 
    438 	__atomic_store_n(&_M_i, __i, __m);
    439       }
    440 
    441       void
    442       store(__int_type __i,
    443 	    memory_order __m = memory_order_seq_cst) volatile noexcept
    444       {
    445 	__glibcxx_assert(__m != memory_order_acquire);
    446 	__glibcxx_assert(__m != memory_order_acq_rel);
    447 	__glibcxx_assert(__m != memory_order_consume);
    448 
    449 	__atomic_store_n(&_M_i, __i, __m);
    450       }
    451 
    452       __int_type
    453       load(memory_order __m = memory_order_seq_cst) const noexcept
    454       {
    455 	__glibcxx_assert(__m != memory_order_release);
    456 	__glibcxx_assert(__m != memory_order_acq_rel);
    457 
    458 	return __atomic_load_n(&_M_i, __m);
    459       }
    460 
    461       __int_type
    462       load(memory_order __m = memory_order_seq_cst) const volatile noexcept
    463       {
    464 	__glibcxx_assert(__m != memory_order_release);
    465 	__glibcxx_assert(__m != memory_order_acq_rel);
    466 
    467 	return __atomic_load_n(&_M_i, __m);
    468       }
    469 
    470       __int_type
    471       exchange(__int_type __i,
    472 	       memory_order __m = memory_order_seq_cst) noexcept
    473       {
    474 	return __atomic_exchange_n(&_M_i, __i, __m);
    475       }
    476 
    477 
    478       __int_type
    479       exchange(__int_type __i,
    480 	       memory_order __m = memory_order_seq_cst) volatile noexcept
    481       {
    482 	return __atomic_exchange_n(&_M_i, __i, __m);
    483       }
    484 
    485       bool
    486       compare_exchange_weak(__int_type& __i1, __int_type __i2,
    487 			    memory_order __m1, memory_order __m2) noexcept
    488       {
    489 	__glibcxx_assert(__m2 != memory_order_release);
    490 	__glibcxx_assert(__m2 != memory_order_acq_rel);
    491 	__glibcxx_assert(__m2 <= __m1);
    492 
    493 	return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, __m1, __m2);
    494       }
    495 
    496       bool
    497       compare_exchange_weak(__int_type& __i1, __int_type __i2,
    498 			    memory_order __m1,
    499 			    memory_order __m2) volatile noexcept
    500       {
    501 	__glibcxx_assert(__m2 != memory_order_release);
    502 	__glibcxx_assert(__m2 != memory_order_acq_rel);
    503 	__glibcxx_assert(__m2 <= __m1);
    504 
    505 	return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, __m1, __m2);
    506       }
    507 
    508       bool
    509       compare_exchange_weak(__int_type& __i1, __int_type __i2,
    510 			    memory_order __m = memory_order_seq_cst) noexcept
    511       {
    512 	return compare_exchange_weak(__i1, __i2, __m,
    513 				     __cmpexch_failure_order(__m));
    514       }
    515 
    516       bool
    517       compare_exchange_weak(__int_type& __i1, __int_type __i2,
    518 		   memory_order __m = memory_order_seq_cst) volatile noexcept
    519       {
    520 	return compare_exchange_weak(__i1, __i2, __m,
    521 				     __cmpexch_failure_order(__m));
    522       }
    523 
    524       bool
    525       compare_exchange_strong(__int_type& __i1, __int_type __i2,
    526 			      memory_order __m1, memory_order __m2) noexcept
    527       {
    528 	__glibcxx_assert(__m2 != memory_order_release);
    529 	__glibcxx_assert(__m2 != memory_order_acq_rel);
    530 	__glibcxx_assert(__m2 <= __m1);
    531 
    532 	return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, __m1, __m2);
    533       }
    534 
    535       bool
    536       compare_exchange_strong(__int_type& __i1, __int_type __i2,
    537 			      memory_order __m1,
    538 			      memory_order __m2) volatile noexcept
    539       {
    540 	__glibcxx_assert(__m2 != memory_order_release);
    541 	__glibcxx_assert(__m2 != memory_order_acq_rel);
    542 	__glibcxx_assert(__m2 <= __m1);
    543 
    544 	return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, __m1, __m2);
    545       }
    546 
    547       bool
    548       compare_exchange_strong(__int_type& __i1, __int_type __i2,
    549 			      memory_order __m = memory_order_seq_cst) noexcept
    550       {
    551 	return compare_exchange_strong(__i1, __i2, __m,
    552 				       __cmpexch_failure_order(__m));
    553       }
    554 
    555       bool
    556       compare_exchange_strong(__int_type& __i1, __int_type __i2,
    557 		 memory_order __m = memory_order_seq_cst) volatile noexcept
    558       {
    559 	return compare_exchange_strong(__i1, __i2, __m,
    560 				       __cmpexch_failure_order(__m));
    561       }
    562 
    563       __int_type
    564       fetch_add(__int_type __i,
    565 		memory_order __m = memory_order_seq_cst) noexcept
    566       { return __atomic_fetch_add(&_M_i, __i, __m); }
    567 
    568       __int_type
    569       fetch_add(__int_type __i,
    570 		memory_order __m = memory_order_seq_cst) volatile noexcept
    571       { return __atomic_fetch_add(&_M_i, __i, __m); }
    572 
    573       __int_type
    574       fetch_sub(__int_type __i,
    575 		memory_order __m = memory_order_seq_cst) noexcept
    576       { return __atomic_fetch_sub(&_M_i, __i, __m); }
    577 
    578       __int_type
    579       fetch_sub(__int_type __i,
    580 		memory_order __m = memory_order_seq_cst) volatile noexcept
    581       { return __atomic_fetch_sub(&_M_i, __i, __m); }
    582 
    583       __int_type
    584       fetch_and(__int_type __i,
    585 		memory_order __m = memory_order_seq_cst) noexcept
    586       { return __atomic_fetch_and(&_M_i, __i, __m); }
    587 
    588       __int_type
    589       fetch_and(__int_type __i,
    590 		memory_order __m = memory_order_seq_cst) volatile noexcept
    591       { return __atomic_fetch_and(&_M_i, __i, __m); }
    592 
    593       __int_type
    594       fetch_or(__int_type __i,
    595 	       memory_order __m = memory_order_seq_cst) noexcept
    596       { return __atomic_fetch_or(&_M_i, __i, __m); }
    597 
    598       __int_type
    599       fetch_or(__int_type __i,
    600 	       memory_order __m = memory_order_seq_cst) volatile noexcept
    601       { return __atomic_fetch_or(&_M_i, __i, __m); }
    602 
    603       __int_type
    604       fetch_xor(__int_type __i,
    605 		memory_order __m = memory_order_seq_cst) noexcept
    606       { return __atomic_fetch_xor(&_M_i, __i, __m); }
    607 
    608       __int_type
    609       fetch_xor(__int_type __i,
    610 		memory_order __m = memory_order_seq_cst) volatile noexcept
    611       { return __atomic_fetch_xor(&_M_i, __i, __m); }
    612     };
    613 
    614 
    615   /// Partial specialization for pointer types.
    616   template<typename _PTp>
    617     struct __atomic_base<_PTp*>
    618     {
    619     private:
    620       typedef _PTp* 	__pointer_type;
    621 
    622       __pointer_type 	_M_p;
    623 
    624       // Factored out to facilitate explicit specialization.
    625       constexpr ptrdiff_t
    626       _M_type_size(ptrdiff_t __d) { return __d * sizeof(_PTp); }
    627 
    628       constexpr ptrdiff_t
    629       _M_type_size(ptrdiff_t __d) volatile { return __d * sizeof(_PTp); }
    630 
    631     public:
    632       __atomic_base() noexcept = default;
    633       ~__atomic_base() noexcept = default;
    634       __atomic_base(const __atomic_base&) = delete;
    635       __atomic_base& operator=(const __atomic_base&) = delete;
    636       __atomic_base& operator=(const __atomic_base&) volatile = delete;
    637 
    638       // Requires __pointer_type convertible to _M_p.
    639       constexpr __atomic_base(__pointer_type __p) noexcept : _M_p (__p) { }
    640 
    641       operator __pointer_type() const noexcept
    642       { return load(); }
    643 
    644       operator __pointer_type() const volatile noexcept
    645       { return load(); }
    646 
    647       __pointer_type
    648       operator=(__pointer_type __p) noexcept
    649       {
    650 	store(__p);
    651 	return __p;
    652       }
    653 
    654       __pointer_type
    655       operator=(__pointer_type __p) volatile noexcept
    656       {
    657 	store(__p);
    658 	return __p;
    659       }
    660 
    661       __pointer_type
    662       operator++(int) noexcept
    663       { return fetch_add(1); }
    664 
    665       __pointer_type
    666       operator++(int) volatile noexcept
    667       { return fetch_add(1); }
    668 
    669       __pointer_type
    670       operator--(int) noexcept
    671       { return fetch_sub(1); }
    672 
    673       __pointer_type
    674       operator--(int) volatile noexcept
    675       { return fetch_sub(1); }
    676 
    677       __pointer_type
    678       operator++() noexcept
    679       { return __atomic_add_fetch(&_M_p, _M_type_size(1),
    680 				  memory_order_seq_cst); }
    681 
    682       __pointer_type
    683       operator++() volatile noexcept
    684       { return __atomic_add_fetch(&_M_p, _M_type_size(1),
    685 				  memory_order_seq_cst); }
    686 
    687       __pointer_type
    688       operator--() noexcept
    689       { return __atomic_sub_fetch(&_M_p, _M_type_size(1),
    690 				  memory_order_seq_cst); }
    691 
    692       __pointer_type
    693       operator--() volatile noexcept
    694       { return __atomic_sub_fetch(&_M_p, _M_type_size(1),
    695 				  memory_order_seq_cst); }
    696 
    697       __pointer_type
    698       operator+=(ptrdiff_t __d) noexcept
    699       { return __atomic_add_fetch(&_M_p, _M_type_size(__d),
    700 				  memory_order_seq_cst); }
    701 
    702       __pointer_type
    703       operator+=(ptrdiff_t __d) volatile noexcept
    704       { return __atomic_add_fetch(&_M_p, _M_type_size(__d),
    705 				  memory_order_seq_cst); }
    706 
    707       __pointer_type
    708       operator-=(ptrdiff_t __d) noexcept
    709       { return __atomic_sub_fetch(&_M_p, _M_type_size(__d),
    710 				  memory_order_seq_cst); }
    711 
    712       __pointer_type
    713       operator-=(ptrdiff_t __d) volatile noexcept
    714       { return __atomic_sub_fetch(&_M_p, _M_type_size(__d),
    715 				  memory_order_seq_cst); }
    716 
    717       bool
    718       is_lock_free() const noexcept
    719       { return __atomic_is_lock_free(_M_type_size(1), &_M_p); }
    720 
    721       bool
    722       is_lock_free() const volatile noexcept
    723       { return __atomic_is_lock_free(_M_type_size(1), &_M_p); }
    724 
    725       void
    726       store(__pointer_type __p,
    727 	    memory_order __m = memory_order_seq_cst) noexcept
    728       {
    729 	__glibcxx_assert(__m != memory_order_acquire);
    730 	__glibcxx_assert(__m != memory_order_acq_rel);
    731 	__glibcxx_assert(__m != memory_order_consume);
    732 
    733 	__atomic_store_n(&_M_p, __p, __m);
    734       }
    735 
    736       void
    737       store(__pointer_type __p,
    738 	    memory_order __m = memory_order_seq_cst) volatile noexcept
    739       {
    740 	__glibcxx_assert(__m != memory_order_acquire);
    741 	__glibcxx_assert(__m != memory_order_acq_rel);
    742 	__glibcxx_assert(__m != memory_order_consume);
    743 
    744 	__atomic_store_n(&_M_p, __p, __m);
    745       }
    746 
    747       __pointer_type
    748       load(memory_order __m = memory_order_seq_cst) const noexcept
    749       {
    750 	__glibcxx_assert(__m != memory_order_release);
    751 	__glibcxx_assert(__m != memory_order_acq_rel);
    752 
    753 	return __atomic_load_n(&_M_p, __m);
    754       }
    755 
    756       __pointer_type
    757       load(memory_order __m = memory_order_seq_cst) const volatile noexcept
    758       {
    759 	__glibcxx_assert(__m != memory_order_release);
    760 	__glibcxx_assert(__m != memory_order_acq_rel);
    761 
    762 	return __atomic_load_n(&_M_p, __m);
    763       }
    764 
    765       __pointer_type
    766       exchange(__pointer_type __p,
    767 	       memory_order __m = memory_order_seq_cst) noexcept
    768       {
    769 	return __atomic_exchange_n(&_M_p, __p, __m);
    770       }
    771 
    772 
    773       __pointer_type
    774       exchange(__pointer_type __p,
    775 	       memory_order __m = memory_order_seq_cst) volatile noexcept
    776       {
    777 	return __atomic_exchange_n(&_M_p, __p, __m);
    778       }
    779 
    780       bool
    781       compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
    782 			      memory_order __m1,
    783 			      memory_order __m2) noexcept
    784       {
    785 	__glibcxx_assert(__m2 != memory_order_release);
    786 	__glibcxx_assert(__m2 != memory_order_acq_rel);
    787 	__glibcxx_assert(__m2 <= __m1);
    788 
    789 	return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, __m1, __m2);
    790       }
    791 
    792       bool
    793       compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
    794 			      memory_order __m1,
    795 			      memory_order __m2) volatile noexcept
    796       {
    797 	__glibcxx_assert(__m2 != memory_order_release);
    798 	__glibcxx_assert(__m2 != memory_order_acq_rel);
    799 	__glibcxx_assert(__m2 <= __m1);
    800 
    801 	return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, __m1, __m2);
    802       }
    803 
    804       __pointer_type
    805       fetch_add(ptrdiff_t __d,
    806 		memory_order __m = memory_order_seq_cst) noexcept
    807       { return __atomic_fetch_add(&_M_p, _M_type_size(__d), __m); }
    808 
    809       __pointer_type
    810       fetch_add(ptrdiff_t __d,
    811 		memory_order __m = memory_order_seq_cst) volatile noexcept
    812       { return __atomic_fetch_add(&_M_p, _M_type_size(__d), __m); }
    813 
    814       __pointer_type
    815       fetch_sub(ptrdiff_t __d,
    816 		memory_order __m = memory_order_seq_cst) noexcept
    817       { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), __m); }
    818 
    819       __pointer_type
    820       fetch_sub(ptrdiff_t __d,
    821 		memory_order __m = memory_order_seq_cst) volatile noexcept
    822       { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), __m); }
    823     };
    824 
    825   // @} group atomics
    826 
    827 _GLIBCXX_END_NAMESPACE_VERSION
    828 } // namespace std
    829 
    830 #endif
    831