libstdc++
atomic_base.h
Go to the documentation of this file.
1 // -*- C++ -*- header.
2 
3 // Copyright (C) 2008-2024 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 <new> // For placement new
37 #include <stdint.h>
39 #include <bits/move.h>
40 
41 #if __cplusplus > 201703L && _GLIBCXX_HOSTED
42 #include <bits/atomic_wait.h>
43 #endif
44 
45 #ifndef _GLIBCXX_ALWAYS_INLINE
46 #define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
47 #endif
48 
49 #include <bits/version.h>
50 
51 namespace std _GLIBCXX_VISIBILITY(default)
52 {
53 _GLIBCXX_BEGIN_NAMESPACE_VERSION
54 
55  /**
56  * @defgroup atomics Atomics
57  *
58  * Components for performing atomic operations.
59  * @{
60  */
61 
62  /// Enumeration for memory_order
63 #if __cplusplus > 201703L
64  enum class memory_order : int
65  {
66  relaxed,
67  consume,
68  acquire,
69  release,
70  acq_rel,
71  seq_cst
72  };
73 
74  inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
75  inline constexpr memory_order memory_order_consume = memory_order::consume;
76  inline constexpr memory_order memory_order_acquire = memory_order::acquire;
77  inline constexpr memory_order memory_order_release = memory_order::release;
78  inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
79  inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst;
80 #else
81  enum memory_order : int
82  {
83  memory_order_relaxed,
84  memory_order_consume,
85  memory_order_acquire,
86  memory_order_release,
87  memory_order_acq_rel,
88  memory_order_seq_cst
89  };
90 #endif
91 
92  /// @cond undocumented
93  enum __memory_order_modifier
94  {
95  __memory_order_mask = 0x0ffff,
96  __memory_order_modifier_mask = 0xffff0000,
97  __memory_order_hle_acquire = 0x10000,
98  __memory_order_hle_release = 0x20000
99  };
100  /// @endcond
101 
102  constexpr memory_order
103  operator|(memory_order __m, __memory_order_modifier __mod) noexcept
104  {
105  return memory_order(int(__m) | int(__mod));
106  }
107 
108  constexpr memory_order
109  operator&(memory_order __m, __memory_order_modifier __mod) noexcept
110  {
111  return memory_order(int(__m) & int(__mod));
112  }
113 
114  /// @cond undocumented
115 
116  // Drop release ordering as per [atomics.types.operations.req]/21
117  constexpr memory_order
118  __cmpexch_failure_order2(memory_order __m) noexcept
119  {
120  return __m == memory_order_acq_rel ? memory_order_acquire
121  : __m == memory_order_release ? memory_order_relaxed : __m;
122  }
123 
124  constexpr memory_order
125  __cmpexch_failure_order(memory_order __m) noexcept
126  {
127  return memory_order(__cmpexch_failure_order2(__m & __memory_order_mask)
128  | __memory_order_modifier(__m & __memory_order_modifier_mask));
129  }
130 
131  constexpr bool
132  __is_valid_cmpexch_failure_order(memory_order __m) noexcept
133  {
134  return (__m & __memory_order_mask) != memory_order_release
135  && (__m & __memory_order_mask) != memory_order_acq_rel;
136  }
137 
138  // Base types for atomics.
139  template<typename _IntTp>
140  struct __atomic_base;
141 
142  /// @endcond
143 
144  _GLIBCXX_ALWAYS_INLINE void
145  atomic_thread_fence(memory_order __m) noexcept
146  { __atomic_thread_fence(int(__m)); }
147 
148  _GLIBCXX_ALWAYS_INLINE void
149  atomic_signal_fence(memory_order __m) noexcept
150  { __atomic_signal_fence(int(__m)); }
151 
152  /// kill_dependency
153  template<typename _Tp>
154  inline _Tp
155  kill_dependency(_Tp __y) noexcept
156  {
157  _Tp __ret(__y);
158  return __ret;
159  }
160 
161 /// @cond undocumented
162 #if __glibcxx_atomic_value_initialization
163 # define _GLIBCXX20_INIT(I) = I
164 #else
165 # define _GLIBCXX20_INIT(I)
166 #endif
167 /// @endcond
168 
169 #define ATOMIC_VAR_INIT(_VI) { _VI }
170 
171  template<typename _Tp>
172  struct atomic;
173 
174  template<typename _Tp>
175  struct atomic<_Tp*>;
176 
177  /* The target's "set" value for test-and-set may not be exactly 1. */
178 #if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1
179  typedef bool __atomic_flag_data_type;
180 #else
181  typedef unsigned char __atomic_flag_data_type;
182 #endif
183 
184  /// @cond undocumented
185 
186  /*
187  * Base type for atomic_flag.
188  *
189  * Base type is POD with data, allowing atomic_flag to derive from
190  * it and meet the standard layout type requirement. In addition to
191  * compatibility with a C interface, this allows different
192  * implementations of atomic_flag to use the same atomic operation
193  * functions, via a standard conversion to the __atomic_flag_base
194  * argument.
195  */
196  _GLIBCXX_BEGIN_EXTERN_C
197 
198  struct __atomic_flag_base
199  {
200  __atomic_flag_data_type _M_i _GLIBCXX20_INIT({});
201  };
202 
203  _GLIBCXX_END_EXTERN_C
204 
205  /// @endcond
206 
207 #define ATOMIC_FLAG_INIT { 0 }
208 
209  /// atomic_flag
210  struct atomic_flag : public __atomic_flag_base
211  {
212  atomic_flag() noexcept = default;
213  ~atomic_flag() noexcept = default;
214  atomic_flag(const atomic_flag&) = delete;
215  atomic_flag& operator=(const atomic_flag&) = delete;
216  atomic_flag& operator=(const atomic_flag&) volatile = delete;
217 
218  // Conversion to ATOMIC_FLAG_INIT.
219  constexpr atomic_flag(bool __i) noexcept
220  : __atomic_flag_base{ _S_init(__i) }
221  { }
222 
223  _GLIBCXX_ALWAYS_INLINE bool
224  test_and_set(memory_order __m = memory_order_seq_cst) noexcept
225  {
226  return __atomic_test_and_set (&_M_i, int(__m));
227  }
228 
229  _GLIBCXX_ALWAYS_INLINE bool
230  test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept
231  {
232  return __atomic_test_and_set (&_M_i, int(__m));
233  }
234 
235 #ifdef __glibcxx_atomic_flag_test // C++ >= 20
236  _GLIBCXX_ALWAYS_INLINE bool
237  test(memory_order __m = memory_order_seq_cst) const noexcept
238  {
239  __atomic_flag_data_type __v;
240  __atomic_load(&_M_i, &__v, int(__m));
241  return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL;
242  }
243 
244  _GLIBCXX_ALWAYS_INLINE bool
245  test(memory_order __m = memory_order_seq_cst) const volatile noexcept
246  {
247  __atomic_flag_data_type __v;
248  __atomic_load(&_M_i, &__v, int(__m));
249  return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL;
250  }
251 #endif
252 
253 #if __glibcxx_atomic_wait // C++ >= 20 && (linux_futex || gthread)
254  _GLIBCXX_ALWAYS_INLINE void
255  wait(bool __old,
256  memory_order __m = memory_order_seq_cst) const noexcept
257  {
258  const __atomic_flag_data_type __v
259  = __old ? __GCC_ATOMIC_TEST_AND_SET_TRUEVAL : 0;
260 
261  std::__atomic_wait_address_v(&_M_i, __v,
262  [__m, this] { return __atomic_load_n(&_M_i, int(__m)); });
263  }
264 
265  // TODO add const volatile overload
266 
267  _GLIBCXX_ALWAYS_INLINE void
268  notify_one() noexcept
269  { std::__atomic_notify_address(&_M_i, false); }
270 
271  // TODO add const volatile overload
272 
273  _GLIBCXX_ALWAYS_INLINE void
274  notify_all() noexcept
275  { std::__atomic_notify_address(&_M_i, true); }
276 
277  // TODO add const volatile overload
278 #endif // __glibcxx_atomic_wait
279 
280  _GLIBCXX_ALWAYS_INLINE void
281  clear(memory_order __m = memory_order_seq_cst) noexcept
282  {
283  memory_order __b __attribute__ ((__unused__))
284  = __m & __memory_order_mask;
285  __glibcxx_assert(__b != memory_order_consume);
286  __glibcxx_assert(__b != memory_order_acquire);
287  __glibcxx_assert(__b != memory_order_acq_rel);
288 
289  __atomic_clear (&_M_i, int(__m));
290  }
291 
292  _GLIBCXX_ALWAYS_INLINE void
293  clear(memory_order __m = memory_order_seq_cst) volatile noexcept
294  {
295  memory_order __b __attribute__ ((__unused__))
296  = __m & __memory_order_mask;
297  __glibcxx_assert(__b != memory_order_consume);
298  __glibcxx_assert(__b != memory_order_acquire);
299  __glibcxx_assert(__b != memory_order_acq_rel);
300 
301  __atomic_clear (&_M_i, int(__m));
302  }
303 
304  private:
305  static constexpr __atomic_flag_data_type
306  _S_init(bool __i)
307  { return __i ? __GCC_ATOMIC_TEST_AND_SET_TRUEVAL : 0; }
308  };
309 
310  /// @cond undocumented
311 
312  /// Base class for atomic integrals.
313  //
314  // For each of the integral types, define atomic_[integral type] struct
315  //
316  // atomic_bool bool
317  // atomic_char char
318  // atomic_schar signed char
319  // atomic_uchar unsigned char
320  // atomic_short short
321  // atomic_ushort unsigned short
322  // atomic_int int
323  // atomic_uint unsigned int
324  // atomic_long long
325  // atomic_ulong unsigned long
326  // atomic_llong long long
327  // atomic_ullong unsigned long long
328  // atomic_char8_t char8_t
329  // atomic_char16_t char16_t
330  // atomic_char32_t char32_t
331  // atomic_wchar_t wchar_t
332  //
333  // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or
334  // 8 bytes, since that is what GCC built-in functions for atomic
335  // memory access expect.
336  template<typename _ITp>
337  struct __atomic_base
338  {
339  using value_type = _ITp;
340  using difference_type = value_type;
341 
342  private:
343  typedef _ITp __int_type;
344 
345  static constexpr int _S_alignment =
346  sizeof(_ITp) > alignof(_ITp) ? sizeof(_ITp) : alignof(_ITp);
347 
348  alignas(_S_alignment) __int_type _M_i _GLIBCXX20_INIT(0);
349 
350  public:
351  __atomic_base() noexcept = default;
352  ~__atomic_base() noexcept = default;
353  __atomic_base(const __atomic_base&) = delete;
354  __atomic_base& operator=(const __atomic_base&) = delete;
355  __atomic_base& operator=(const __atomic_base&) volatile = delete;
356 
357  // Requires __int_type convertible to _M_i.
358  constexpr __atomic_base(__int_type __i) noexcept : _M_i (__i) { }
359 
360  operator __int_type() const noexcept
361  { return load(); }
362 
363  operator __int_type() const volatile noexcept
364  { return load(); }
365 
366  __int_type
367  operator=(__int_type __i) noexcept
368  {
369  store(__i);
370  return __i;
371  }
372 
373  __int_type
374  operator=(__int_type __i) volatile noexcept
375  {
376  store(__i);
377  return __i;
378  }
379 
380  __int_type
381  operator++(int) noexcept
382  { return fetch_add(1); }
383 
384  __int_type
385  operator++(int) volatile noexcept
386  { return fetch_add(1); }
387 
388  __int_type
389  operator--(int) noexcept
390  { return fetch_sub(1); }
391 
392  __int_type
393  operator--(int) volatile noexcept
394  { return fetch_sub(1); }
395 
396  __int_type
397  operator++() noexcept
398  { return __atomic_add_fetch(&_M_i, 1, int(memory_order_seq_cst)); }
399 
400  __int_type
401  operator++() volatile noexcept
402  { return __atomic_add_fetch(&_M_i, 1, int(memory_order_seq_cst)); }
403 
404  __int_type
405  operator--() noexcept
406  { return __atomic_sub_fetch(&_M_i, 1, int(memory_order_seq_cst)); }
407 
408  __int_type
409  operator--() volatile noexcept
410  { return __atomic_sub_fetch(&_M_i, 1, int(memory_order_seq_cst)); }
411 
412  __int_type
413  operator+=(__int_type __i) noexcept
414  { return __atomic_add_fetch(&_M_i, __i, int(memory_order_seq_cst)); }
415 
416  __int_type
417  operator+=(__int_type __i) volatile noexcept
418  { return __atomic_add_fetch(&_M_i, __i, int(memory_order_seq_cst)); }
419 
420  __int_type
421  operator-=(__int_type __i) noexcept
422  { return __atomic_sub_fetch(&_M_i, __i, int(memory_order_seq_cst)); }
423 
424  __int_type
425  operator-=(__int_type __i) volatile noexcept
426  { return __atomic_sub_fetch(&_M_i, __i, int(memory_order_seq_cst)); }
427 
428  __int_type
429  operator&=(__int_type __i) noexcept
430  { return __atomic_and_fetch(&_M_i, __i, int(memory_order_seq_cst)); }
431 
432  __int_type
433  operator&=(__int_type __i) volatile noexcept
434  { return __atomic_and_fetch(&_M_i, __i, int(memory_order_seq_cst)); }
435 
436  __int_type
437  operator|=(__int_type __i) noexcept
438  { return __atomic_or_fetch(&_M_i, __i, int(memory_order_seq_cst)); }
439 
440  __int_type
441  operator|=(__int_type __i) volatile noexcept
442  { return __atomic_or_fetch(&_M_i, __i, int(memory_order_seq_cst)); }
443 
444  __int_type
445  operator^=(__int_type __i) noexcept
446  { return __atomic_xor_fetch(&_M_i, __i, int(memory_order_seq_cst)); }
447 
448  __int_type
449  operator^=(__int_type __i) volatile noexcept
450  { return __atomic_xor_fetch(&_M_i, __i, int(memory_order_seq_cst)); }
451 
452  bool
453  is_lock_free() const noexcept
454  {
455  // Use a fake, minimally aligned pointer.
456  return __atomic_is_lock_free(sizeof(_M_i),
457  reinterpret_cast<void *>(-_S_alignment));
458  }
459 
460  bool
461  is_lock_free() const volatile noexcept
462  {
463  // Use a fake, minimally aligned pointer.
464  return __atomic_is_lock_free(sizeof(_M_i),
465  reinterpret_cast<void *>(-_S_alignment));
466  }
467 
468  _GLIBCXX_ALWAYS_INLINE void
469  store(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept
470  {
471  memory_order __b __attribute__ ((__unused__))
472  = __m & __memory_order_mask;
473  __glibcxx_assert(__b != memory_order_acquire);
474  __glibcxx_assert(__b != memory_order_acq_rel);
475  __glibcxx_assert(__b != memory_order_consume);
476 
477  __atomic_store_n(&_M_i, __i, int(__m));
478  }
479 
480  _GLIBCXX_ALWAYS_INLINE void
481  store(__int_type __i,
482  memory_order __m = memory_order_seq_cst) volatile noexcept
483  {
484  memory_order __b __attribute__ ((__unused__))
485  = __m & __memory_order_mask;
486  __glibcxx_assert(__b != memory_order_acquire);
487  __glibcxx_assert(__b != memory_order_acq_rel);
488  __glibcxx_assert(__b != memory_order_consume);
489 
490  __atomic_store_n(&_M_i, __i, int(__m));
491  }
492 
493  _GLIBCXX_ALWAYS_INLINE __int_type
494  load(memory_order __m = memory_order_seq_cst) const noexcept
495  {
496  memory_order __b __attribute__ ((__unused__))
497  = __m & __memory_order_mask;
498  __glibcxx_assert(__b != memory_order_release);
499  __glibcxx_assert(__b != memory_order_acq_rel);
500 
501  return __atomic_load_n(&_M_i, int(__m));
502  }
503 
504  _GLIBCXX_ALWAYS_INLINE __int_type
505  load(memory_order __m = memory_order_seq_cst) const volatile noexcept
506  {
507  memory_order __b __attribute__ ((__unused__))
508  = __m & __memory_order_mask;
509  __glibcxx_assert(__b != memory_order_release);
510  __glibcxx_assert(__b != memory_order_acq_rel);
511 
512  return __atomic_load_n(&_M_i, int(__m));
513  }
514 
515  _GLIBCXX_ALWAYS_INLINE __int_type
516  exchange(__int_type __i,
517  memory_order __m = memory_order_seq_cst) noexcept
518  {
519  return __atomic_exchange_n(&_M_i, __i, int(__m));
520  }
521 
522 
523  _GLIBCXX_ALWAYS_INLINE __int_type
524  exchange(__int_type __i,
525  memory_order __m = memory_order_seq_cst) volatile noexcept
526  {
527  return __atomic_exchange_n(&_M_i, __i, int(__m));
528  }
529 
530  _GLIBCXX_ALWAYS_INLINE bool
531  compare_exchange_weak(__int_type& __i1, __int_type __i2,
532  memory_order __m1, memory_order __m2) noexcept
533  {
534  __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
535 
536  return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1,
537  int(__m1), int(__m2));
538  }
539 
540  _GLIBCXX_ALWAYS_INLINE bool
541  compare_exchange_weak(__int_type& __i1, __int_type __i2,
542  memory_order __m1,
543  memory_order __m2) volatile noexcept
544  {
545  __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
546 
547  return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1,
548  int(__m1), int(__m2));
549  }
550 
551  _GLIBCXX_ALWAYS_INLINE bool
552  compare_exchange_weak(__int_type& __i1, __int_type __i2,
553  memory_order __m = memory_order_seq_cst) noexcept
554  {
555  return compare_exchange_weak(__i1, __i2, __m,
556  __cmpexch_failure_order(__m));
557  }
558 
559  _GLIBCXX_ALWAYS_INLINE bool
560  compare_exchange_weak(__int_type& __i1, __int_type __i2,
561  memory_order __m = memory_order_seq_cst) volatile noexcept
562  {
563  return compare_exchange_weak(__i1, __i2, __m,
564  __cmpexch_failure_order(__m));
565  }
566 
567  _GLIBCXX_ALWAYS_INLINE bool
568  compare_exchange_strong(__int_type& __i1, __int_type __i2,
569  memory_order __m1, memory_order __m2) noexcept
570  {
571  __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
572 
573  return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0,
574  int(__m1), int(__m2));
575  }
576 
577  _GLIBCXX_ALWAYS_INLINE bool
578  compare_exchange_strong(__int_type& __i1, __int_type __i2,
579  memory_order __m1,
580  memory_order __m2) volatile noexcept
581  {
582  __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
583 
584  return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0,
585  int(__m1), int(__m2));
586  }
587 
588  _GLIBCXX_ALWAYS_INLINE bool
589  compare_exchange_strong(__int_type& __i1, __int_type __i2,
590  memory_order __m = memory_order_seq_cst) noexcept
591  {
592  return compare_exchange_strong(__i1, __i2, __m,
593  __cmpexch_failure_order(__m));
594  }
595 
596  _GLIBCXX_ALWAYS_INLINE bool
597  compare_exchange_strong(__int_type& __i1, __int_type __i2,
598  memory_order __m = memory_order_seq_cst) volatile noexcept
599  {
600  return compare_exchange_strong(__i1, __i2, __m,
601  __cmpexch_failure_order(__m));
602  }
603 
604 #if __glibcxx_atomic_wait
605  _GLIBCXX_ALWAYS_INLINE void
606  wait(__int_type __old,
607  memory_order __m = memory_order_seq_cst) const noexcept
608  {
609  std::__atomic_wait_address_v(&_M_i, __old,
610  [__m, this] { return this->load(__m); });
611  }
612 
613  // TODO add const volatile overload
614 
615  _GLIBCXX_ALWAYS_INLINE void
616  notify_one() noexcept
617  { std::__atomic_notify_address(&_M_i, false); }
618 
619  // TODO add const volatile overload
620 
621  _GLIBCXX_ALWAYS_INLINE void
622  notify_all() noexcept
623  { std::__atomic_notify_address(&_M_i, true); }
624 
625  // TODO add const volatile overload
626 #endif // __glibcxx_atomic_wait
627 
628  _GLIBCXX_ALWAYS_INLINE __int_type
629  fetch_add(__int_type __i,
630  memory_order __m = memory_order_seq_cst) noexcept
631  { return __atomic_fetch_add(&_M_i, __i, int(__m)); }
632 
633  _GLIBCXX_ALWAYS_INLINE __int_type
634  fetch_add(__int_type __i,
635  memory_order __m = memory_order_seq_cst) volatile noexcept
636  { return __atomic_fetch_add(&_M_i, __i, int(__m)); }
637 
638  _GLIBCXX_ALWAYS_INLINE __int_type
639  fetch_sub(__int_type __i,
640  memory_order __m = memory_order_seq_cst) noexcept
641  { return __atomic_fetch_sub(&_M_i, __i, int(__m)); }
642 
643  _GLIBCXX_ALWAYS_INLINE __int_type
644  fetch_sub(__int_type __i,
645  memory_order __m = memory_order_seq_cst) volatile noexcept
646  { return __atomic_fetch_sub(&_M_i, __i, int(__m)); }
647 
648  _GLIBCXX_ALWAYS_INLINE __int_type
649  fetch_and(__int_type __i,
650  memory_order __m = memory_order_seq_cst) noexcept
651  { return __atomic_fetch_and(&_M_i, __i, int(__m)); }
652 
653  _GLIBCXX_ALWAYS_INLINE __int_type
654  fetch_and(__int_type __i,
655  memory_order __m = memory_order_seq_cst) volatile noexcept
656  { return __atomic_fetch_and(&_M_i, __i, int(__m)); }
657 
658  _GLIBCXX_ALWAYS_INLINE __int_type
659  fetch_or(__int_type __i,
660  memory_order __m = memory_order_seq_cst) noexcept
661  { return __atomic_fetch_or(&_M_i, __i, int(__m)); }
662 
663  _GLIBCXX_ALWAYS_INLINE __int_type
664  fetch_or(__int_type __i,
665  memory_order __m = memory_order_seq_cst) volatile noexcept
666  { return __atomic_fetch_or(&_M_i, __i, int(__m)); }
667 
668  _GLIBCXX_ALWAYS_INLINE __int_type
669  fetch_xor(__int_type __i,
670  memory_order __m = memory_order_seq_cst) noexcept
671  { return __atomic_fetch_xor(&_M_i, __i, int(__m)); }
672 
673  _GLIBCXX_ALWAYS_INLINE __int_type
674  fetch_xor(__int_type __i,
675  memory_order __m = memory_order_seq_cst) volatile noexcept
676  { return __atomic_fetch_xor(&_M_i, __i, int(__m)); }
677  };
678 
679 
680  /// Partial specialization for pointer types.
681  template<typename _PTp>
682  struct __atomic_base<_PTp*>
683  {
684  private:
685  typedef _PTp* __pointer_type;
686 
687  __pointer_type _M_p _GLIBCXX20_INIT(nullptr);
688 
689  static constexpr ptrdiff_t
690  _S_type_size(ptrdiff_t __d)
691  { return __d * sizeof(_PTp); }
692 
693  public:
694  __atomic_base() noexcept = default;
695  ~__atomic_base() noexcept = default;
696  __atomic_base(const __atomic_base&) = delete;
697  __atomic_base& operator=(const __atomic_base&) = delete;
698  __atomic_base& operator=(const __atomic_base&) volatile = delete;
699 
700  // Requires __pointer_type convertible to _M_p.
701  constexpr __atomic_base(__pointer_type __p) noexcept : _M_p (__p) { }
702 
703  operator __pointer_type() const noexcept
704  { return load(); }
705 
706  operator __pointer_type() const volatile noexcept
707  { return load(); }
708 
709  __pointer_type
710  operator=(__pointer_type __p) noexcept
711  {
712  store(__p);
713  return __p;
714  }
715 
716  __pointer_type
717  operator=(__pointer_type __p) volatile noexcept
718  {
719  store(__p);
720  return __p;
721  }
722 
723  __pointer_type
724  operator++(int) noexcept
725  { return fetch_add(1); }
726 
727  __pointer_type
728  operator++(int) volatile noexcept
729  { return fetch_add(1); }
730 
731  __pointer_type
732  operator--(int) noexcept
733  { return fetch_sub(1); }
734 
735  __pointer_type
736  operator--(int) volatile noexcept
737  { return fetch_sub(1); }
738 
739  __pointer_type
740  operator++() noexcept
741  { return __atomic_add_fetch(&_M_p, _S_type_size(1),
742  int(memory_order_seq_cst)); }
743 
744  __pointer_type
745  operator++() volatile noexcept
746  { return __atomic_add_fetch(&_M_p, _S_type_size(1),
747  int(memory_order_seq_cst)); }
748 
749  __pointer_type
750  operator--() noexcept
751  { return __atomic_sub_fetch(&_M_p, _S_type_size(1),
752  int(memory_order_seq_cst)); }
753 
754  __pointer_type
755  operator--() volatile noexcept
756  { return __atomic_sub_fetch(&_M_p, _S_type_size(1),
757  int(memory_order_seq_cst)); }
758 
759  __pointer_type
760  operator+=(ptrdiff_t __d) noexcept
761  { return __atomic_add_fetch(&_M_p, _S_type_size(__d),
762  int(memory_order_seq_cst)); }
763 
764  __pointer_type
765  operator+=(ptrdiff_t __d) volatile noexcept
766  { return __atomic_add_fetch(&_M_p, _S_type_size(__d),
767  int(memory_order_seq_cst)); }
768 
769  __pointer_type
770  operator-=(ptrdiff_t __d) noexcept
771  { return __atomic_sub_fetch(&_M_p, _S_type_size(__d),
772  int(memory_order_seq_cst)); }
773 
774  __pointer_type
775  operator-=(ptrdiff_t __d) volatile noexcept
776  { return __atomic_sub_fetch(&_M_p, _S_type_size(__d),
777  int(memory_order_seq_cst)); }
778 
779  bool
780  is_lock_free() const noexcept
781  {
782  // Produce a fake, minimally aligned pointer.
783  return __atomic_is_lock_free(sizeof(_M_p),
784  reinterpret_cast<void *>(-__alignof(_M_p)));
785  }
786 
787  bool
788  is_lock_free() const volatile noexcept
789  {
790  // Produce a fake, minimally aligned pointer.
791  return __atomic_is_lock_free(sizeof(_M_p),
792  reinterpret_cast<void *>(-__alignof(_M_p)));
793  }
794 
795  _GLIBCXX_ALWAYS_INLINE void
796  store(__pointer_type __p,
797  memory_order __m = memory_order_seq_cst) noexcept
798  {
799  memory_order __b __attribute__ ((__unused__))
800  = __m & __memory_order_mask;
801 
802  __glibcxx_assert(__b != memory_order_acquire);
803  __glibcxx_assert(__b != memory_order_acq_rel);
804  __glibcxx_assert(__b != memory_order_consume);
805 
806  __atomic_store_n(&_M_p, __p, int(__m));
807  }
808 
809  _GLIBCXX_ALWAYS_INLINE void
810  store(__pointer_type __p,
811  memory_order __m = memory_order_seq_cst) volatile noexcept
812  {
813  memory_order __b __attribute__ ((__unused__))
814  = __m & __memory_order_mask;
815  __glibcxx_assert(__b != memory_order_acquire);
816  __glibcxx_assert(__b != memory_order_acq_rel);
817  __glibcxx_assert(__b != memory_order_consume);
818 
819  __atomic_store_n(&_M_p, __p, int(__m));
820  }
821 
822  _GLIBCXX_ALWAYS_INLINE __pointer_type
823  load(memory_order __m = memory_order_seq_cst) const noexcept
824  {
825  memory_order __b __attribute__ ((__unused__))
826  = __m & __memory_order_mask;
827  __glibcxx_assert(__b != memory_order_release);
828  __glibcxx_assert(__b != memory_order_acq_rel);
829 
830  return __atomic_load_n(&_M_p, int(__m));
831  }
832 
833  _GLIBCXX_ALWAYS_INLINE __pointer_type
834  load(memory_order __m = memory_order_seq_cst) const volatile noexcept
835  {
836  memory_order __b __attribute__ ((__unused__))
837  = __m & __memory_order_mask;
838  __glibcxx_assert(__b != memory_order_release);
839  __glibcxx_assert(__b != memory_order_acq_rel);
840 
841  return __atomic_load_n(&_M_p, int(__m));
842  }
843 
844  _GLIBCXX_ALWAYS_INLINE __pointer_type
845  exchange(__pointer_type __p,
846  memory_order __m = memory_order_seq_cst) noexcept
847  {
848  return __atomic_exchange_n(&_M_p, __p, int(__m));
849  }
850 
851 
852  _GLIBCXX_ALWAYS_INLINE __pointer_type
853  exchange(__pointer_type __p,
854  memory_order __m = memory_order_seq_cst) volatile noexcept
855  {
856  return __atomic_exchange_n(&_M_p, __p, int(__m));
857  }
858 
859  _GLIBCXX_ALWAYS_INLINE bool
860  compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2,
861  memory_order __m1,
862  memory_order __m2) noexcept
863  {
864  __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
865 
866  return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 1,
867  int(__m1), int(__m2));
868  }
869 
870  _GLIBCXX_ALWAYS_INLINE bool
871  compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2,
872  memory_order __m1,
873  memory_order __m2) volatile noexcept
874  {
875  __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
876 
877  return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 1,
878  int(__m1), int(__m2));
879  }
880 
881  _GLIBCXX_ALWAYS_INLINE bool
882  compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
883  memory_order __m1,
884  memory_order __m2) noexcept
885  {
886  __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
887 
888  return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0,
889  int(__m1), int(__m2));
890  }
891 
892  _GLIBCXX_ALWAYS_INLINE bool
893  compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
894  memory_order __m1,
895  memory_order __m2) volatile noexcept
896  {
897  __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
898 
899  return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0,
900  int(__m1), int(__m2));
901  }
902 
903 #if __glibcxx_atomic_wait
904  _GLIBCXX_ALWAYS_INLINE void
905  wait(__pointer_type __old,
906  memory_order __m = memory_order_seq_cst) const noexcept
907  {
908  std::__atomic_wait_address_v(&_M_p, __old,
909  [__m, this]
910  { return this->load(__m); });
911  }
912 
913  // TODO add const volatile overload
914 
915  _GLIBCXX_ALWAYS_INLINE void
916  notify_one() const noexcept
917  { std::__atomic_notify_address(&_M_p, false); }
918 
919  // TODO add const volatile overload
920 
921  _GLIBCXX_ALWAYS_INLINE void
922  notify_all() const noexcept
923  { std::__atomic_notify_address(&_M_p, true); }
924 
925  // TODO add const volatile overload
926 #endif // __glibcxx_atomic_wait
927 
928  _GLIBCXX_ALWAYS_INLINE __pointer_type
929  fetch_add(ptrdiff_t __d,
930  memory_order __m = memory_order_seq_cst) noexcept
931  { return __atomic_fetch_add(&_M_p, _S_type_size(__d), int(__m)); }
932 
933  _GLIBCXX_ALWAYS_INLINE __pointer_type
934  fetch_add(ptrdiff_t __d,
935  memory_order __m = memory_order_seq_cst) volatile noexcept
936  { return __atomic_fetch_add(&_M_p, _S_type_size(__d), int(__m)); }
937 
938  _GLIBCXX_ALWAYS_INLINE __pointer_type
939  fetch_sub(ptrdiff_t __d,
940  memory_order __m = memory_order_seq_cst) noexcept
941  { return __atomic_fetch_sub(&_M_p, _S_type_size(__d), int(__m)); }
942 
943  _GLIBCXX_ALWAYS_INLINE __pointer_type
944  fetch_sub(ptrdiff_t __d,
945  memory_order __m = memory_order_seq_cst) volatile noexcept
946  { return __atomic_fetch_sub(&_M_p, _S_type_size(__d), int(__m)); }
947  };
948 
949  namespace __atomic_impl
950  {
951  // Implementation details of atomic padding handling
952 
953  template<typename _Tp>
954  constexpr bool
955  __maybe_has_padding()
956  {
957 #if ! __has_builtin(__builtin_clear_padding)
958  return false;
959 #elif __has_builtin(__has_unique_object_representations)
960  return !__has_unique_object_representations(_Tp)
961  && !is_same<_Tp, float>::value && !is_same<_Tp, double>::value;
962 #else
963  return true;
964 #endif
965  }
966 
967  template<typename _Tp>
968  _GLIBCXX_ALWAYS_INLINE _GLIBCXX14_CONSTEXPR _Tp*
969  __clear_padding(_Tp& __val) noexcept
970  {
971  auto* __ptr = std::__addressof(__val);
972 #if __has_builtin(__builtin_clear_padding)
973  if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Tp>())
974  __builtin_clear_padding(__ptr);
975 #endif
976  return __ptr;
977  }
978 
979  // Remove volatile and create a non-deduced context for value arguments.
980  template<typename _Tp>
981  using _Val = typename remove_volatile<_Tp>::type;
982 
983 #pragma GCC diagnostic push
984 #pragma GCC diagnostic ignored "-Wc++17-extensions"
985 
986  template<bool _AtomicRef = false, typename _Tp>
987  _GLIBCXX_ALWAYS_INLINE bool
988  __compare_exchange(_Tp& __val, _Val<_Tp>& __e, _Val<_Tp>& __i,
989  bool __is_weak,
990  memory_order __s, memory_order __f) noexcept
991  {
992  __glibcxx_assert(__is_valid_cmpexch_failure_order(__f));
993 
994  using _Vp = _Val<_Tp>;
995  _Tp* const __pval = std::__addressof(__val);
996 
997  if constexpr (!__atomic_impl::__maybe_has_padding<_Vp>())
998  {
999  return __atomic_compare_exchange(__pval, std::__addressof(__e),
1000  std::__addressof(__i), __is_weak,
1001  int(__s), int(__f));
1002  }
1003  else if constexpr (!_AtomicRef) // std::atomic<T>
1004  {
1005  // Clear padding of the value we want to set:
1006  _Vp* const __pi = __atomic_impl::__clear_padding(__i);
1007  // Only allowed to modify __e on failure, so make a copy:
1008  _Vp __exp = __e;
1009  // Clear padding of the expected value:
1010  _Vp* const __pexp = __atomic_impl::__clear_padding(__exp);
1011 
1012  // For std::atomic<T> we know that the contained value will already
1013  // have zeroed padding, so trivial memcmp semantics are OK.
1014  if (__atomic_compare_exchange(__pval, __pexp, __pi,
1015  __is_weak, int(__s), int(__f)))
1016  return true;
1017  // Value bits must be different, copy from __exp back to __e:
1018  __builtin_memcpy(std::__addressof(__e), __pexp, sizeof(_Vp));
1019  return false;
1020  }
1021  else // std::atomic_ref<T> where T has padding bits.
1022  {
1023  // Clear padding of the value we want to set:
1024  _Vp* const __pi = __atomic_impl::__clear_padding(__i);
1025 
1026  // Only allowed to modify __e on failure, so make a copy:
1027  _Vp __exp = __e;
1028  // Optimistically assume that a previous store had zeroed padding
1029  // so that zeroing it in the expected value will match first time.
1030  _Vp* const __pexp = __atomic_impl::__clear_padding(__exp);
1031 
1032  // compare_exchange is specified to compare value representations.
1033  // Need to check whether a failure is 'real' or just due to
1034  // differences in padding bits. This loop should run no more than
1035  // three times, because the worst case scenario is:
1036  // First CAS fails because the actual value has non-zero padding.
1037  // Second CAS fails because another thread stored the same value,
1038  // but now with padding cleared. Third CAS succeeds.
1039  // We will never need to loop a fourth time, because any value
1040  // written by another thread (whether via store, exchange or
1041  // compare_exchange) will have had its padding cleared.
1042  while (true)
1043  {
1044  // Copy of the expected value so we can clear its padding.
1045  _Vp __orig = __exp;
1046 
1047  if (__atomic_compare_exchange(__pval, __pexp, __pi,
1048  __is_weak, int(__s), int(__f)))
1049  return true;
1050 
1051  // Copy of the actual value so we can clear its padding.
1052  _Vp __curr = __exp;
1053 
1054  // Compare value representations (i.e. ignoring padding).
1055  if (__builtin_memcmp(__atomic_impl::__clear_padding(__orig),
1056  __atomic_impl::__clear_padding(__curr),
1057  sizeof(_Vp)))
1058  {
1059  // Value representations compare unequal, real failure.
1060  __builtin_memcpy(std::__addressof(__e), __pexp,
1061  sizeof(_Vp));
1062  return false;
1063  }
1064  }
1065  }
1066  }
1067 #pragma GCC diagnostic pop
1068  } // namespace __atomic_impl
1069 
1070 #if __cplusplus > 201703L
1071  // Implementation details of atomic_ref and atomic<floating-point>.
1072  namespace __atomic_impl
1073  {
1074  // Like _Val<T> above, but for difference_type arguments.
1075  template<typename _Tp>
1076  using _Diff = __conditional_t<is_pointer_v<_Tp>, ptrdiff_t, _Val<_Tp>>;
1077 
1078  template<size_t _Size, size_t _Align>
1079  _GLIBCXX_ALWAYS_INLINE bool
1080  is_lock_free() noexcept
1081  {
1082  // Produce a fake, minimally aligned pointer.
1083  return __atomic_is_lock_free(_Size, reinterpret_cast<void *>(-_Align));
1084  }
1085 
1086  template<typename _Tp>
1087  _GLIBCXX_ALWAYS_INLINE void
1088  store(_Tp* __ptr, _Val<_Tp> __t, memory_order __m) noexcept
1089  {
1090  __atomic_store(__ptr, __atomic_impl::__clear_padding(__t), int(__m));
1091  }
1092 
1093  template<typename _Tp>
1094  _GLIBCXX_ALWAYS_INLINE _Val<_Tp>
1095  load(const _Tp* __ptr, memory_order __m) noexcept
1096  {
1097  alignas(_Tp) unsigned char __buf[sizeof(_Tp)];
1098  auto* __dest = reinterpret_cast<_Val<_Tp>*>(__buf);
1099  __atomic_load(__ptr, __dest, int(__m));
1100  return *__dest;
1101  }
1102 
1103  template<typename _Tp>
1104  _GLIBCXX_ALWAYS_INLINE _Val<_Tp>
1105  exchange(_Tp* __ptr, _Val<_Tp> __desired, memory_order __m) noexcept
1106  {
1107  alignas(_Tp) unsigned char __buf[sizeof(_Tp)];
1108  auto* __dest = reinterpret_cast<_Val<_Tp>*>(__buf);
1109  __atomic_exchange(__ptr, __atomic_impl::__clear_padding(__desired),
1110  __dest, int(__m));
1111  return *__dest;
1112  }
1113 
1114  template<bool _AtomicRef = false, typename _Tp>
1115  _GLIBCXX_ALWAYS_INLINE bool
1116  compare_exchange_weak(_Tp* __ptr, _Val<_Tp>& __expected,
1117  _Val<_Tp> __desired, memory_order __success,
1118  memory_order __failure,
1119  bool __check_padding = false) noexcept
1120  {
1121  return __atomic_impl::__compare_exchange<_AtomicRef>(
1122  *__ptr, __expected, __desired, true, __success, __failure);
1123  }
1124 
1125  template<bool _AtomicRef = false, typename _Tp>
1126  _GLIBCXX_ALWAYS_INLINE bool
1127  compare_exchange_strong(_Tp* __ptr, _Val<_Tp>& __expected,
1128  _Val<_Tp> __desired, memory_order __success,
1129  memory_order __failure,
1130  bool __ignore_padding = false) noexcept
1131  {
1132  return __atomic_impl::__compare_exchange<_AtomicRef>(
1133  *__ptr, __expected, __desired, false, __success, __failure);
1134  }
1135 
1136 #if __glibcxx_atomic_wait
1137  template<typename _Tp>
1138  _GLIBCXX_ALWAYS_INLINE void
1139  wait(const _Tp* __ptr, _Val<_Tp> __old,
1140  memory_order __m = memory_order_seq_cst) noexcept
1141  {
1142  std::__atomic_wait_address_v(__ptr, __old,
1143  [__ptr, __m]() { return __atomic_impl::load(__ptr, __m); });
1144  }
1145 
1146  // TODO add const volatile overload
1147 
1148  template<typename _Tp>
1149  _GLIBCXX_ALWAYS_INLINE void
1150  notify_one(const _Tp* __ptr) noexcept
1151  { std::__atomic_notify_address(__ptr, false); }
1152 
1153  // TODO add const volatile overload
1154 
1155  template<typename _Tp>
1156  _GLIBCXX_ALWAYS_INLINE void
1157  notify_all(const _Tp* __ptr) noexcept
1158  { std::__atomic_notify_address(__ptr, true); }
1159 
1160  // TODO add const volatile overload
1161 #endif // __glibcxx_atomic_wait
1162 
1163  template<typename _Tp>
1164  _GLIBCXX_ALWAYS_INLINE _Tp
1165  fetch_add(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m) noexcept
1166  { return __atomic_fetch_add(__ptr, __i, int(__m)); }
1167 
1168  template<typename _Tp>
1169  _GLIBCXX_ALWAYS_INLINE _Tp
1170  fetch_sub(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m) noexcept
1171  { return __atomic_fetch_sub(__ptr, __i, int(__m)); }
1172 
1173  template<typename _Tp>
1174  _GLIBCXX_ALWAYS_INLINE _Tp
1175  fetch_and(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept
1176  { return __atomic_fetch_and(__ptr, __i, int(__m)); }
1177 
1178  template<typename _Tp>
1179  _GLIBCXX_ALWAYS_INLINE _Tp
1180  fetch_or(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept
1181  { return __atomic_fetch_or(__ptr, __i, int(__m)); }
1182 
1183  template<typename _Tp>
1184  _GLIBCXX_ALWAYS_INLINE _Tp
1185  fetch_xor(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept
1186  { return __atomic_fetch_xor(__ptr, __i, int(__m)); }
1187 
1188  template<typename _Tp>
1189  _GLIBCXX_ALWAYS_INLINE _Tp
1190  __add_fetch(_Tp* __ptr, _Diff<_Tp> __i) noexcept
1191  { return __atomic_add_fetch(__ptr, __i, __ATOMIC_SEQ_CST); }
1192 
1193  template<typename _Tp>
1194  _GLIBCXX_ALWAYS_INLINE _Tp
1195  __sub_fetch(_Tp* __ptr, _Diff<_Tp> __i) noexcept
1196  { return __atomic_sub_fetch(__ptr, __i, __ATOMIC_SEQ_CST); }
1197 
1198  template<typename _Tp>
1199  _GLIBCXX_ALWAYS_INLINE _Tp
1200  __and_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept
1201  { return __atomic_and_fetch(__ptr, __i, __ATOMIC_SEQ_CST); }
1202 
1203  template<typename _Tp>
1204  _GLIBCXX_ALWAYS_INLINE _Tp
1205  __or_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept
1206  { return __atomic_or_fetch(__ptr, __i, __ATOMIC_SEQ_CST); }
1207 
1208  template<typename _Tp>
1209  _GLIBCXX_ALWAYS_INLINE _Tp
1210  __xor_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept
1211  { return __atomic_xor_fetch(__ptr, __i, __ATOMIC_SEQ_CST); }
1212 
1213  template<typename _Tp>
1214  _Tp
1215  __fetch_add_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept
1216  {
1217  _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed);
1218  _Val<_Tp> __newval = __oldval + __i;
1219  while (!compare_exchange_weak(__ptr, __oldval, __newval, __m,
1220  memory_order_relaxed))
1221  __newval = __oldval + __i;
1222  return __oldval;
1223  }
1224 
1225  template<typename _Tp>
1226  _Tp
1227  __fetch_sub_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept
1228  {
1229  _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed);
1230  _Val<_Tp> __newval = __oldval - __i;
1231  while (!compare_exchange_weak(__ptr, __oldval, __newval, __m,
1232  memory_order_relaxed))
1233  __newval = __oldval - __i;
1234  return __oldval;
1235  }
1236 
1237  template<typename _Tp>
1238  _Tp
1239  __add_fetch_flt(_Tp* __ptr, _Val<_Tp> __i) noexcept
1240  {
1241  _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed);
1242  _Val<_Tp> __newval = __oldval + __i;
1243  while (!compare_exchange_weak(__ptr, __oldval, __newval,
1244  memory_order_seq_cst,
1245  memory_order_relaxed))
1246  __newval = __oldval + __i;
1247  return __newval;
1248  }
1249 
1250  template<typename _Tp>
1251  _Tp
1252  __sub_fetch_flt(_Tp* __ptr, _Val<_Tp> __i) noexcept
1253  {
1254  _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed);
1255  _Val<_Tp> __newval = __oldval - __i;
1256  while (!compare_exchange_weak(__ptr, __oldval, __newval,
1257  memory_order_seq_cst,
1258  memory_order_relaxed))
1259  __newval = __oldval - __i;
1260  return __newval;
1261  }
1262  } // namespace __atomic_impl
1263 
1264  // base class for atomic<floating-point-type>
1265  template<typename _Fp>
1266  struct __atomic_float
1267  {
1268  static_assert(is_floating_point_v<_Fp>);
1269 
1270  static constexpr size_t _S_alignment = __alignof__(_Fp);
1271 
1272  public:
1273  using value_type = _Fp;
1274  using difference_type = value_type;
1275 
1276  static constexpr bool is_always_lock_free
1277  = __atomic_always_lock_free(sizeof(_Fp), 0);
1278 
1279  __atomic_float() = default;
1280 
1281  constexpr
1282  __atomic_float(_Fp __t) : _M_fp(__t)
1283  { __atomic_impl::__clear_padding(_M_fp); }
1284 
1285  __atomic_float(const __atomic_float&) = delete;
1286  __atomic_float& operator=(const __atomic_float&) = delete;
1287  __atomic_float& operator=(const __atomic_float&) volatile = delete;
1288 
1289  _Fp
1290  operator=(_Fp __t) volatile noexcept
1291  {
1292  this->store(__t);
1293  return __t;
1294  }
1295 
1296  _Fp
1297  operator=(_Fp __t) noexcept
1298  {
1299  this->store(__t);
1300  return __t;
1301  }
1302 
1303  bool
1304  is_lock_free() const volatile noexcept
1305  { return __atomic_impl::is_lock_free<sizeof(_Fp), _S_alignment>(); }
1306 
1307  bool
1308  is_lock_free() const noexcept
1309  { return __atomic_impl::is_lock_free<sizeof(_Fp), _S_alignment>(); }
1310 
1311  void
1312  store(_Fp __t, memory_order __m = memory_order_seq_cst) volatile noexcept
1313  { __atomic_impl::store(&_M_fp, __t, __m); }
1314 
1315  void
1316  store(_Fp __t, memory_order __m = memory_order_seq_cst) noexcept
1317  { __atomic_impl::store(&_M_fp, __t, __m); }
1318 
1319  _Fp
1320  load(memory_order __m = memory_order_seq_cst) const volatile noexcept
1321  { return __atomic_impl::load(&_M_fp, __m); }
1322 
1323  _Fp
1324  load(memory_order __m = memory_order_seq_cst) const noexcept
1325  { return __atomic_impl::load(&_M_fp, __m); }
1326 
1327  operator _Fp() const volatile noexcept { return this->load(); }
1328  operator _Fp() const noexcept { return this->load(); }
1329 
1330  _Fp
1331  exchange(_Fp __desired,
1332  memory_order __m = memory_order_seq_cst) volatile noexcept
1333  { return __atomic_impl::exchange(&_M_fp, __desired, __m); }
1334 
1335  _Fp
1336  exchange(_Fp __desired,
1337  memory_order __m = memory_order_seq_cst) noexcept
1338  { return __atomic_impl::exchange(&_M_fp, __desired, __m); }
1339 
1340  bool
1341  compare_exchange_weak(_Fp& __expected, _Fp __desired,
1342  memory_order __success,
1343  memory_order __failure) noexcept
1344  {
1345  return __atomic_impl::compare_exchange_weak(&_M_fp,
1346  __expected, __desired,
1347  __success, __failure);
1348  }
1349 
1350  bool
1351  compare_exchange_weak(_Fp& __expected, _Fp __desired,
1352  memory_order __success,
1353  memory_order __failure) volatile noexcept
1354  {
1355  return __atomic_impl::compare_exchange_weak(&_M_fp,
1356  __expected, __desired,
1357  __success, __failure);
1358  }
1359 
1360  bool
1361  compare_exchange_strong(_Fp& __expected, _Fp __desired,
1362  memory_order __success,
1363  memory_order __failure) noexcept
1364  {
1365  return __atomic_impl::compare_exchange_strong(&_M_fp,
1366  __expected, __desired,
1367  __success, __failure);
1368  }
1369 
1370  bool
1371  compare_exchange_strong(_Fp& __expected, _Fp __desired,
1372  memory_order __success,
1373  memory_order __failure) volatile noexcept
1374  {
1375  return __atomic_impl::compare_exchange_strong(&_M_fp,
1376  __expected, __desired,
1377  __success, __failure);
1378  }
1379 
1380  bool
1381  compare_exchange_weak(_Fp& __expected, _Fp __desired,
1382  memory_order __order = memory_order_seq_cst)
1383  noexcept
1384  {
1385  return compare_exchange_weak(__expected, __desired, __order,
1386  __cmpexch_failure_order(__order));
1387  }
1388 
1389  bool
1390  compare_exchange_weak(_Fp& __expected, _Fp __desired,
1391  memory_order __order = memory_order_seq_cst)
1392  volatile noexcept
1393  {
1394  return compare_exchange_weak(__expected, __desired, __order,
1395  __cmpexch_failure_order(__order));
1396  }
1397 
1398  bool
1399  compare_exchange_strong(_Fp& __expected, _Fp __desired,
1400  memory_order __order = memory_order_seq_cst)
1401  noexcept
1402  {
1403  return compare_exchange_strong(__expected, __desired, __order,
1404  __cmpexch_failure_order(__order));
1405  }
1406 
1407  bool
1408  compare_exchange_strong(_Fp& __expected, _Fp __desired,
1409  memory_order __order = memory_order_seq_cst)
1410  volatile noexcept
1411  {
1412  return compare_exchange_strong(__expected, __desired, __order,
1413  __cmpexch_failure_order(__order));
1414  }
1415 
1416 #if __glibcxx_atomic_wait
1417  _GLIBCXX_ALWAYS_INLINE void
1418  wait(_Fp __old, memory_order __m = memory_order_seq_cst) const noexcept
1419  { __atomic_impl::wait(&_M_fp, __old, __m); }
1420 
1421  // TODO add const volatile overload
1422 
1423  _GLIBCXX_ALWAYS_INLINE void
1424  notify_one() const noexcept
1425  { __atomic_impl::notify_one(&_M_fp); }
1426 
1427  // TODO add const volatile overload
1428 
1429  _GLIBCXX_ALWAYS_INLINE void
1430  notify_all() const noexcept
1431  { __atomic_impl::notify_all(&_M_fp); }
1432 
1433  // TODO add const volatile overload
1434 #endif // __glibcxx_atomic_wait
1435 
1436  value_type
1437  fetch_add(value_type __i,
1438  memory_order __m = memory_order_seq_cst) noexcept
1439  { return __atomic_impl::__fetch_add_flt(&_M_fp, __i, __m); }
1440 
1441  value_type
1442  fetch_add(value_type __i,
1443  memory_order __m = memory_order_seq_cst) volatile noexcept
1444  { return __atomic_impl::__fetch_add_flt(&_M_fp, __i, __m); }
1445 
1446  value_type
1447  fetch_sub(value_type __i,
1448  memory_order __m = memory_order_seq_cst) noexcept
1449  { return __atomic_impl::__fetch_sub_flt(&_M_fp, __i, __m); }
1450 
1451  value_type
1452  fetch_sub(value_type __i,
1453  memory_order __m = memory_order_seq_cst) volatile noexcept
1454  { return __atomic_impl::__fetch_sub_flt(&_M_fp, __i, __m); }
1455 
1456  value_type
1457  operator+=(value_type __i) noexcept
1458  { return __atomic_impl::__add_fetch_flt(&_M_fp, __i); }
1459 
1460  value_type
1461  operator+=(value_type __i) volatile noexcept
1462  { return __atomic_impl::__add_fetch_flt(&_M_fp, __i); }
1463 
1464  value_type
1465  operator-=(value_type __i) noexcept
1466  { return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); }
1467 
1468  value_type
1469  operator-=(value_type __i) volatile noexcept
1470  { return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); }
1471 
1472  private:
1473  alignas(_S_alignment) _Fp _M_fp _GLIBCXX20_INIT(0);
1474  };
1475 #undef _GLIBCXX20_INIT
1476 
1477  template<typename _Tp,
1478  bool = is_integral_v<_Tp>, bool = is_floating_point_v<_Tp>>
1479  struct __atomic_ref;
1480 
1481  // base class for non-integral, non-floating-point, non-pointer types
1482  template<typename _Tp>
1483  struct __atomic_ref<_Tp, false, false>
1484  {
1485  static_assert(is_trivially_copyable_v<_Tp>);
1486 
1487  // 1/2/4/8/16-byte types must be aligned to at least their size.
1488  static constexpr int _S_min_alignment
1489  = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || sizeof(_Tp) > 16
1490  ? 0 : sizeof(_Tp);
1491 
1492  public:
1493  using value_type = _Tp;
1494 
1495  static constexpr bool is_always_lock_free
1496  = __atomic_always_lock_free(sizeof(_Tp), 0);
1497 
1498  static constexpr size_t required_alignment
1499  = _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp);
1500 
1501  __atomic_ref& operator=(const __atomic_ref&) = delete;
1502 
1503  explicit
1504  __atomic_ref(_Tp& __t) : _M_ptr(std::__addressof(__t))
1505  { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); }
1506 
1507  __atomic_ref(const __atomic_ref&) noexcept = default;
1508 
1509  _Tp
1510  operator=(_Tp __t) const noexcept
1511  {
1512  this->store(__t);
1513  return __t;
1514  }
1515 
1516  operator _Tp() const noexcept { return this->load(); }
1517 
1518  bool
1519  is_lock_free() const noexcept
1520  { return __atomic_impl::is_lock_free<sizeof(_Tp), required_alignment>(); }
1521 
1522  void
1523  store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept
1524  { __atomic_impl::store(_M_ptr, __t, __m); }
1525 
1526  _Tp
1527  load(memory_order __m = memory_order_seq_cst) const noexcept
1528  { return __atomic_impl::load(_M_ptr, __m); }
1529 
1530  _Tp
1531  exchange(_Tp __desired, memory_order __m = memory_order_seq_cst)
1532  const noexcept
1533  { return __atomic_impl::exchange(_M_ptr, __desired, __m); }
1534 
1535  bool
1536  compare_exchange_weak(_Tp& __expected, _Tp __desired,
1537  memory_order __success,
1538  memory_order __failure) const noexcept
1539  {
1540  return __atomic_impl::compare_exchange_weak<true>(
1541  _M_ptr, __expected, __desired, __success, __failure);
1542  }
1543 
1544  bool
1545  compare_exchange_strong(_Tp& __expected, _Tp __desired,
1546  memory_order __success,
1547  memory_order __failure) const noexcept
1548  {
1549  return __atomic_impl::compare_exchange_strong<true>(
1550  _M_ptr, __expected, __desired, __success, __failure);
1551  }
1552 
1553  bool
1554  compare_exchange_weak(_Tp& __expected, _Tp __desired,
1555  memory_order __order = memory_order_seq_cst)
1556  const noexcept
1557  {
1558  return compare_exchange_weak(__expected, __desired, __order,
1559  __cmpexch_failure_order(__order));
1560  }
1561 
1562  bool
1563  compare_exchange_strong(_Tp& __expected, _Tp __desired,
1564  memory_order __order = memory_order_seq_cst)
1565  const noexcept
1566  {
1567  return compare_exchange_strong(__expected, __desired, __order,
1568  __cmpexch_failure_order(__order));
1569  }
1570 
1571 #if __glibcxx_atomic_wait
1572  _GLIBCXX_ALWAYS_INLINE void
1573  wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept
1574  { __atomic_impl::wait(_M_ptr, __old, __m); }
1575 
1576  // TODO add const volatile overload
1577 
1578  _GLIBCXX_ALWAYS_INLINE void
1579  notify_one() const noexcept
1580  { __atomic_impl::notify_one(_M_ptr); }
1581 
1582  // TODO add const volatile overload
1583 
1584  _GLIBCXX_ALWAYS_INLINE void
1585  notify_all() const noexcept
1586  { __atomic_impl::notify_all(_M_ptr); }
1587 
1588  // TODO add const volatile overload
1589 #endif // __glibcxx_atomic_wait
1590 
1591  private:
1592  _Tp* _M_ptr;
1593  };
1594 
1595  // base class for atomic_ref<integral-type>
1596  template<typename _Tp>
1597  struct __atomic_ref<_Tp, true, false>
1598  {
1599  static_assert(is_integral_v<_Tp>);
1600 
1601  public:
1602  using value_type = _Tp;
1603  using difference_type = value_type;
1604 
1605  static constexpr bool is_always_lock_free
1606  = __atomic_always_lock_free(sizeof(_Tp), 0);
1607 
1608  static constexpr size_t required_alignment
1609  = sizeof(_Tp) > alignof(_Tp) ? sizeof(_Tp) : alignof(_Tp);
1610 
1611  __atomic_ref() = delete;
1612  __atomic_ref& operator=(const __atomic_ref&) = delete;
1613 
1614  explicit
1615  __atomic_ref(_Tp& __t) : _M_ptr(&__t)
1616  { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); }
1617 
1618  __atomic_ref(const __atomic_ref&) noexcept = default;
1619 
1620  _Tp
1621  operator=(_Tp __t) const noexcept
1622  {
1623  this->store(__t);
1624  return __t;
1625  }
1626 
1627  operator _Tp() const noexcept { return this->load(); }
1628 
1629  bool
1630  is_lock_free() const noexcept
1631  {
1632  return __atomic_impl::is_lock_free<sizeof(_Tp), required_alignment>();
1633  }
1634 
1635  void
1636  store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept
1637  { __atomic_impl::store(_M_ptr, __t, __m); }
1638 
1639  _Tp
1640  load(memory_order __m = memory_order_seq_cst) const noexcept
1641  { return __atomic_impl::load(_M_ptr, __m); }
1642 
1643  _Tp
1644  exchange(_Tp __desired,
1645  memory_order __m = memory_order_seq_cst) const noexcept
1646  { return __atomic_impl::exchange(_M_ptr, __desired, __m); }
1647 
1648  bool
1649  compare_exchange_weak(_Tp& __expected, _Tp __desired,
1650  memory_order __success,
1651  memory_order __failure) const noexcept
1652  {
1653  return __atomic_impl::compare_exchange_weak<true>(
1654  _M_ptr, __expected, __desired, __success, __failure);
1655  }
1656 
1657  bool
1658  compare_exchange_strong(_Tp& __expected, _Tp __desired,
1659  memory_order __success,
1660  memory_order __failure) const noexcept
1661  {
1662  return __atomic_impl::compare_exchange_strong<true>(
1663  _M_ptr, __expected, __desired, __success, __failure);
1664  }
1665 
1666  bool
1667  compare_exchange_weak(_Tp& __expected, _Tp __desired,
1668  memory_order __order = memory_order_seq_cst)
1669  const noexcept
1670  {
1671  return compare_exchange_weak(__expected, __desired, __order,
1672  __cmpexch_failure_order(__order));
1673  }
1674 
1675  bool
1676  compare_exchange_strong(_Tp& __expected, _Tp __desired,
1677  memory_order __order = memory_order_seq_cst)
1678  const noexcept
1679  {
1680  return compare_exchange_strong(__expected, __desired, __order,
1681  __cmpexch_failure_order(__order));
1682  }
1683 
1684 #if __glibcxx_atomic_wait
1685  _GLIBCXX_ALWAYS_INLINE void
1686  wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept
1687  { __atomic_impl::wait(_M_ptr, __old, __m); }
1688 
1689  // TODO add const volatile overload
1690 
1691  _GLIBCXX_ALWAYS_INLINE void
1692  notify_one() const noexcept
1693  { __atomic_impl::notify_one(_M_ptr); }
1694 
1695  // TODO add const volatile overload
1696 
1697  _GLIBCXX_ALWAYS_INLINE void
1698  notify_all() const noexcept
1699  { __atomic_impl::notify_all(_M_ptr); }
1700 
1701  // TODO add const volatile overload
1702 #endif // __glibcxx_atomic_wait
1703 
1704  value_type
1705  fetch_add(value_type __i,
1706  memory_order __m = memory_order_seq_cst) const noexcept
1707  { return __atomic_impl::fetch_add(_M_ptr, __i, __m); }
1708 
1709  value_type
1710  fetch_sub(value_type __i,
1711  memory_order __m = memory_order_seq_cst) const noexcept
1712  { return __atomic_impl::fetch_sub(_M_ptr, __i, __m); }
1713 
1714  value_type
1715  fetch_and(value_type __i,
1716  memory_order __m = memory_order_seq_cst) const noexcept
1717  { return __atomic_impl::fetch_and(_M_ptr, __i, __m); }
1718 
1719  value_type
1720  fetch_or(value_type __i,
1721  memory_order __m = memory_order_seq_cst) const noexcept
1722  { return __atomic_impl::fetch_or(_M_ptr, __i, __m); }
1723 
1724  value_type
1725  fetch_xor(value_type __i,
1726  memory_order __m = memory_order_seq_cst) const noexcept
1727  { return __atomic_impl::fetch_xor(_M_ptr, __i, __m); }
1728 
1729  _GLIBCXX_ALWAYS_INLINE value_type
1730  operator++(int) const noexcept
1731  { return fetch_add(1); }
1732 
1733  _GLIBCXX_ALWAYS_INLINE value_type
1734  operator--(int) const noexcept
1735  { return fetch_sub(1); }
1736 
1737  value_type
1738  operator++() const noexcept
1739  { return __atomic_impl::__add_fetch(_M_ptr, value_type(1)); }
1740 
1741  value_type
1742  operator--() const noexcept
1743  { return __atomic_impl::__sub_fetch(_M_ptr, value_type(1)); }
1744 
1745  value_type
1746  operator+=(value_type __i) const noexcept
1747  { return __atomic_impl::__add_fetch(_M_ptr, __i); }
1748 
1749  value_type
1750  operator-=(value_type __i) const noexcept
1751  { return __atomic_impl::__sub_fetch(_M_ptr, __i); }
1752 
1753  value_type
1754  operator&=(value_type __i) const noexcept
1755  { return __atomic_impl::__and_fetch(_M_ptr, __i); }
1756 
1757  value_type
1758  operator|=(value_type __i) const noexcept
1759  { return __atomic_impl::__or_fetch(_M_ptr, __i); }
1760 
1761  value_type
1762  operator^=(value_type __i) const noexcept
1763  { return __atomic_impl::__xor_fetch(_M_ptr, __i); }
1764 
1765  private:
1766  _Tp* _M_ptr;
1767  };
1768 
1769  // base class for atomic_ref<floating-point-type>
1770  template<typename _Fp>
1771  struct __atomic_ref<_Fp, false, true>
1772  {
1773  static_assert(is_floating_point_v<_Fp>);
1774 
1775  public:
1776  using value_type = _Fp;
1777  using difference_type = value_type;
1778 
1779  static constexpr bool is_always_lock_free
1780  = __atomic_always_lock_free(sizeof(_Fp), 0);
1781 
1782  static constexpr size_t required_alignment = __alignof__(_Fp);
1783 
1784  __atomic_ref() = delete;
1785  __atomic_ref& operator=(const __atomic_ref&) = delete;
1786 
1787  explicit
1788  __atomic_ref(_Fp& __t) : _M_ptr(&__t)
1789  { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); }
1790 
1791  __atomic_ref(const __atomic_ref&) noexcept = default;
1792 
1793  _Fp
1794  operator=(_Fp __t) const noexcept
1795  {
1796  this->store(__t);
1797  return __t;
1798  }
1799 
1800  operator _Fp() const noexcept { return this->load(); }
1801 
1802  bool
1803  is_lock_free() const noexcept
1804  {
1805  return __atomic_impl::is_lock_free<sizeof(_Fp), required_alignment>();
1806  }
1807 
1808  void
1809  store(_Fp __t, memory_order __m = memory_order_seq_cst) const noexcept
1810  { __atomic_impl::store(_M_ptr, __t, __m); }
1811 
1812  _Fp
1813  load(memory_order __m = memory_order_seq_cst) const noexcept
1814  { return __atomic_impl::load(_M_ptr, __m); }
1815 
1816  _Fp
1817  exchange(_Fp __desired,
1818  memory_order __m = memory_order_seq_cst) const noexcept
1819  { return __atomic_impl::exchange(_M_ptr, __desired, __m); }
1820 
1821  bool
1822  compare_exchange_weak(_Fp& __expected, _Fp __desired,
1823  memory_order __success,
1824  memory_order __failure) const noexcept
1825  {
1826  return __atomic_impl::compare_exchange_weak<true>(
1827  _M_ptr, __expected, __desired, __success, __failure);
1828  }
1829 
1830  bool
1831  compare_exchange_strong(_Fp& __expected, _Fp __desired,
1832  memory_order __success,
1833  memory_order __failure) const noexcept
1834  {
1835  return __atomic_impl::compare_exchange_strong<true>(
1836  _M_ptr, __expected, __desired, __success, __failure);
1837  }
1838 
1839  bool
1840  compare_exchange_weak(_Fp& __expected, _Fp __desired,
1841  memory_order __order = memory_order_seq_cst)
1842  const noexcept
1843  {
1844  return compare_exchange_weak(__expected, __desired, __order,
1845  __cmpexch_failure_order(__order));
1846  }
1847 
1848  bool
1849  compare_exchange_strong(_Fp& __expected, _Fp __desired,
1850  memory_order __order = memory_order_seq_cst)
1851  const noexcept
1852  {
1853  return compare_exchange_strong(__expected, __desired, __order,
1854  __cmpexch_failure_order(__order));
1855  }
1856 
1857 #if __glibcxx_atomic_wait
1858  _GLIBCXX_ALWAYS_INLINE void
1859  wait(_Fp __old, memory_order __m = memory_order_seq_cst) const noexcept
1860  { __atomic_impl::wait(_M_ptr, __old, __m); }
1861 
1862  // TODO add const volatile overload
1863 
1864  _GLIBCXX_ALWAYS_INLINE void
1865  notify_one() const noexcept
1866  { __atomic_impl::notify_one(_M_ptr); }
1867 
1868  // TODO add const volatile overload
1869 
1870  _GLIBCXX_ALWAYS_INLINE void
1871  notify_all() const noexcept
1872  { __atomic_impl::notify_all(_M_ptr); }
1873 
1874  // TODO add const volatile overload
1875 #endif // __glibcxx_atomic_wait
1876 
1877  value_type
1878  fetch_add(value_type __i,
1879  memory_order __m = memory_order_seq_cst) const noexcept
1880  { return __atomic_impl::__fetch_add_flt(_M_ptr, __i, __m); }
1881 
1882  value_type
1883  fetch_sub(value_type __i,
1884  memory_order __m = memory_order_seq_cst) const noexcept
1885  { return __atomic_impl::__fetch_sub_flt(_M_ptr, __i, __m); }
1886 
1887  value_type
1888  operator+=(value_type __i) const noexcept
1889  { return __atomic_impl::__add_fetch_flt(_M_ptr, __i); }
1890 
1891  value_type
1892  operator-=(value_type __i) const noexcept
1893  { return __atomic_impl::__sub_fetch_flt(_M_ptr, __i); }
1894 
1895  private:
1896  _Fp* _M_ptr;
1897  };
1898 
1899  // base class for atomic_ref<pointer-type>
1900  template<typename _Tp>
1901  struct __atomic_ref<_Tp*, false, false>
1902  {
1903  public:
1904  using value_type = _Tp*;
1905  using difference_type = ptrdiff_t;
1906 
1907  static constexpr bool is_always_lock_free = ATOMIC_POINTER_LOCK_FREE == 2;
1908 
1909  static constexpr size_t required_alignment = __alignof__(_Tp*);
1910 
1911  __atomic_ref() = delete;
1912  __atomic_ref& operator=(const __atomic_ref&) = delete;
1913 
1914  explicit
1915  __atomic_ref(_Tp*& __t) : _M_ptr(std::__addressof(__t))
1916  { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); }
1917 
1918  __atomic_ref(const __atomic_ref&) noexcept = default;
1919 
1920  _Tp*
1921  operator=(_Tp* __t) const noexcept
1922  {
1923  this->store(__t);
1924  return __t;
1925  }
1926 
1927  operator _Tp*() const noexcept { return this->load(); }
1928 
1929  bool
1930  is_lock_free() const noexcept
1931  {
1932  return __atomic_impl::is_lock_free<sizeof(_Tp*), required_alignment>();
1933  }
1934 
1935  void
1936  store(_Tp* __t, memory_order __m = memory_order_seq_cst) const noexcept
1937  { __atomic_impl::store(_M_ptr, __t, __m); }
1938 
1939  _Tp*
1940  load(memory_order __m = memory_order_seq_cst) const noexcept
1941  { return __atomic_impl::load(_M_ptr, __m); }
1942 
1943  _Tp*
1944  exchange(_Tp* __desired,
1945  memory_order __m = memory_order_seq_cst) const noexcept
1946  { return __atomic_impl::exchange(_M_ptr, __desired, __m); }
1947 
1948  bool
1949  compare_exchange_weak(_Tp*& __expected, _Tp* __desired,
1950  memory_order __success,
1951  memory_order __failure) const noexcept
1952  {
1953  return __atomic_impl::compare_exchange_weak<true>(
1954  _M_ptr, __expected, __desired, __success, __failure);
1955  }
1956 
1957  bool
1958  compare_exchange_strong(_Tp*& __expected, _Tp* __desired,
1959  memory_order __success,
1960  memory_order __failure) const noexcept
1961  {
1962  return __atomic_impl::compare_exchange_strong<true>(
1963  _M_ptr, __expected, __desired, __success, __failure);
1964  }
1965 
1966  bool
1967  compare_exchange_weak(_Tp*& __expected, _Tp* __desired,
1968  memory_order __order = memory_order_seq_cst)
1969  const noexcept
1970  {
1971  return compare_exchange_weak(__expected, __desired, __order,
1972  __cmpexch_failure_order(__order));
1973  }
1974 
1975  bool
1976  compare_exchange_strong(_Tp*& __expected, _Tp* __desired,
1977  memory_order __order = memory_order_seq_cst)
1978  const noexcept
1979  {
1980  return compare_exchange_strong(__expected, __desired, __order,
1981  __cmpexch_failure_order(__order));
1982  }
1983 
1984 #if __glibcxx_atomic_wait
1985  _GLIBCXX_ALWAYS_INLINE void
1986  wait(_Tp* __old, memory_order __m = memory_order_seq_cst) const noexcept
1987  { __atomic_impl::wait(_M_ptr, __old, __m); }
1988 
1989  // TODO add const volatile overload
1990 
1991  _GLIBCXX_ALWAYS_INLINE void
1992  notify_one() const noexcept
1993  { __atomic_impl::notify_one(_M_ptr); }
1994 
1995  // TODO add const volatile overload
1996 
1997  _GLIBCXX_ALWAYS_INLINE void
1998  notify_all() const noexcept
1999  { __atomic_impl::notify_all(_M_ptr); }
2000 
2001  // TODO add const volatile overload
2002 #endif // __glibcxx_atomic_wait
2003 
2004  _GLIBCXX_ALWAYS_INLINE value_type
2005  fetch_add(difference_type __d,
2006  memory_order __m = memory_order_seq_cst) const noexcept
2007  { return __atomic_impl::fetch_add(_M_ptr, _S_type_size(__d), __m); }
2008 
2009  _GLIBCXX_ALWAYS_INLINE value_type
2010  fetch_sub(difference_type __d,
2011  memory_order __m = memory_order_seq_cst) const noexcept
2012  { return __atomic_impl::fetch_sub(_M_ptr, _S_type_size(__d), __m); }
2013 
2014  value_type
2015  operator++(int) const noexcept
2016  { return fetch_add(1); }
2017 
2018  value_type
2019  operator--(int) const noexcept
2020  { return fetch_sub(1); }
2021 
2022  value_type
2023  operator++() const noexcept
2024  {
2025  return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(1));
2026  }
2027 
2028  value_type
2029  operator--() const noexcept
2030  {
2031  return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(1));
2032  }
2033 
2034  value_type
2035  operator+=(difference_type __d) const noexcept
2036  {
2037  return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(__d));
2038  }
2039 
2040  value_type
2041  operator-=(difference_type __d) const noexcept
2042  {
2043  return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(__d));
2044  }
2045 
2046  private:
2047  static constexpr ptrdiff_t
2048  _S_type_size(ptrdiff_t __d) noexcept
2049  {
2050  static_assert(is_object_v<_Tp>);
2051  return __d * sizeof(_Tp);
2052  }
2053 
2054  _Tp** _M_ptr;
2055  };
2056 #endif // C++2a
2057 
2058  /// @endcond
2059 
2060  /// @} group atomics
2061 
2062 _GLIBCXX_END_NAMESPACE_VERSION
2063 } // namespace std
2064 
2065 #endif
std::memory_order
memory_order
Enumeration for memory_order.
Definition: atomic_base.h:64
std::kill_dependency
_Tp kill_dependency(_Tp __y) noexcept
kill_dependency
Definition: atomic_base.h:155
version.h
std
ISO C++ entities toplevel namespace is std.
std::atomic_flag
atomic_flag
Definition: atomic_base.h:210
std::__addressof
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:51
atomic_wait.h
move.h
std::operator&
constexpr bitset< _Nb > operator&(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
Definition: bitset:1557
atomic_lockfree_defines.h
std::operator|
constexpr bitset< _Nb > operator|(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
Definition: bitset:1567
new
c++config.h