OSDN Git Service

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