LCOV - code coverage report
Current view: top level - usr/include/c++/9/bits - atomic_base.h (source / functions) Hit Total Coverage
Test: ROSE Lines: 0 12 0.0 %
Date: 2022-12-08 13:48:47 Functions: 0 0 -
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14