libstdc++
atomic_base.h
Go to the documentation of this file.
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>
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>
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 
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
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  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  load(memory_order __m = memory_order_seq_cst) const noexcept
414  {
415  memory_order __b = __m & __memory_order_mask;
416  __glibcxx_assert(__b != memory_order_release);
417  __glibcxx_assert(__b != memory_order_acq_rel);
418 
419  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  compare_exchange_weak(__int_type& __i1, __int_type __i2,
449  memory_order __m1, memory_order __m2) noexcept
450  {
451  memory_order __b2 = __m2 & __memory_order_mask;
452  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  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  fetch_add(__int_type __i,
540  memory_order __m = memory_order_seq_cst) noexcept
541  { 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  fetch_sub(__int_type __i,
550  memory_order __m = memory_order_seq_cst) noexcept
551  { 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
_Tp exchange(_Tp &__obj, _Up &&__new_val)
Assign __new_val to __obj and return its previous value.
Definition: utility:286
atomic_flag
Definition: atomic_base.h:179
memory_order
Enumeration for memory_order.
Definition: atomic_base.h:73
ISO C++ entities toplevel namespace is std.
Base type for atomic_flag.
Definition: atomic_base.h:169
Generic atomic type, primary class template.
Definition: atomic:58
bitset< _Nb > operator &(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
Definition: bitset:1433
bitset< _Nb > operator|(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
Definition: bitset:1442
Base class for atomic integrals.
Definition: atomic_base.h:139
_Tp kill_dependency(_Tp __y) noexcept
kill_dependency
Definition: atomic_base.h:130