OSDN Git Service

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