OSDN Git Service

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