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