Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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