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