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