OSDN Git Service

42ff462701f6a90b1af87cc3adef5af776c095d2
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / atomic_0.h
1 // -*- C++ -*- header.
2
3 // Copyright (C) 2008, 2009, 2010
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
20
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24 // <http://www.gnu.org/licenses/>.
25
26 /** @file bits/atomic_0.h
27  *  This is an internal header file, included by other library headers.
28  *  Do not attempt to use it directly. @headername{atomic}
29  */
30
31 #ifndef _GLIBCXX_ATOMIC_0_H
32 #define _GLIBCXX_ATOMIC_0_H 1
33
34 #pragma GCC system_header
35
36 namespace std _GLIBCXX_VISIBILITY(default)
37 {
38 _GLIBCXX_BEGIN_NAMESPACE_VERSION
39
40 // 0 == __atomic0 == Never lock-free
41 namespace __atomic0
42 {
43   _GLIBCXX_BEGIN_EXTERN_C
44
45   void
46   atomic_flag_clear_explicit(__atomic_flag_base*, memory_order)
47   _GLIBCXX_NOTHROW;
48
49   void
50   __atomic_flag_wait_explicit(__atomic_flag_base*, memory_order)
51   _GLIBCXX_NOTHROW;
52
53   _GLIBCXX_CONST __atomic_flag_base*
54   __atomic_flag_for_address(const volatile void* __z) _GLIBCXX_NOTHROW;
55
56   _GLIBCXX_END_EXTERN_C
57
58   // Implementation specific defines.
59 #define _ATOMIC_MEMBER_ _M_i
60
61   // Implementation specific defines.
62 #define _ATOMIC_LOAD_(__a, __x)                                            \
63   ({typedef __typeof__(_ATOMIC_MEMBER_) __i_type;                          \
64     __i_type* __p = &_ATOMIC_MEMBER_;                                      \
65     __atomic_flag_base* __g = __atomic_flag_for_address(__p);              \
66     __atomic_flag_wait_explicit(__g, __x);                                 \
67     __i_type __r = *__p;                                                   \
68     atomic_flag_clear_explicit(__g, __x);                                  \
69     __r; })
70
71 #define _ATOMIC_STORE_(__a, __m, __x)                                      \
72   ({typedef __typeof__(_ATOMIC_MEMBER_) __i_type;                          \
73     __i_type* __p = &_ATOMIC_MEMBER_;                                      \
74     __typeof__(__m) __v = (__m);                                           \
75     __atomic_flag_base* __g = __atomic_flag_for_address(__p);              \
76     __atomic_flag_wait_explicit(__g, __x);                                 \
77     *__p = __v;                                                            \
78     atomic_flag_clear_explicit(__g, __x);                                  \
79     __v; })
80
81 #define _ATOMIC_MODIFY_(__a, __o, __m, __x)                                \
82   ({typedef __typeof__(_ATOMIC_MEMBER_) __i_type;                          \
83     __i_type* __p = &_ATOMIC_MEMBER_;                                      \
84     __typeof__(__m) __v = (__m);                                           \
85     __atomic_flag_base* __g = __atomic_flag_for_address(__p);              \
86     __atomic_flag_wait_explicit(__g, __x);                                 \
87     __i_type __r = *__p;                                                   \
88     *__p __o __v;                                                          \
89     atomic_flag_clear_explicit(__g, __x);                                  \
90     __r; })
91
92 #define _ATOMIC_CMPEXCHNG_(__a, __e, __m, __x)                             \
93   ({typedef __typeof__(_ATOMIC_MEMBER_) __i_type;                          \
94     __i_type* __p = &_ATOMIC_MEMBER_;                                      \
95     __typeof__(__e) __q = (__e);                                           \
96     __typeof__(__m) __v = (__m);                                           \
97     bool __r;                                                              \
98     __atomic_flag_base* __g = __atomic_flag_for_address(__p);              \
99     __atomic_flag_wait_explicit(__g, __x);                                 \
100     __i_type __t = *__p;                                                   \
101     if (*__q == __t)                                                       \
102     {                                                                      \
103       *__p = (__i_type)__v;                                             \
104       __r = true;                                                          \
105     }                                                                      \
106     else { *__q = __t; __r = false; }                                      \
107     atomic_flag_clear_explicit(__g, __x);                                  \
108     __r; })
109
110
111   /// atomic_flag
112   struct atomic_flag : public __atomic_flag_base
113   {
114     atomic_flag() = default;
115     ~atomic_flag() = default;
116     atomic_flag(const atomic_flag&) = delete;
117     atomic_flag& operator=(const atomic_flag&) = delete;
118     atomic_flag& operator=(const atomic_flag&) volatile = delete;
119
120     // Conversion to ATOMIC_FLAG_INIT.
121     atomic_flag(bool __i): __atomic_flag_base({ __i }) { }
122
123     bool
124     test_and_set(memory_order __m = memory_order_seq_cst);
125
126     bool
127     test_and_set(memory_order __m = memory_order_seq_cst) volatile;
128
129     void
130     clear(memory_order __m = memory_order_seq_cst);
131
132     void
133     clear(memory_order __m = memory_order_seq_cst) volatile;
134   };
135
136
137   /// atomic_address
138   struct atomic_address
139   {
140   private:
141     void* _M_i;
142
143   public:
144     atomic_address() = default;
145     ~atomic_address() = default;
146     atomic_address(const atomic_address&) = delete;
147     atomic_address& operator=(const atomic_address&) = delete;
148     atomic_address& operator=(const atomic_address&) volatile = delete;
149
150     constexpr atomic_address(void* __v): _M_i (__v) { }
151
152     bool
153     is_lock_free() const { return false; }
154
155     bool
156     is_lock_free() const volatile { return false; }
157
158     void
159     store(void* __v, memory_order __m = memory_order_seq_cst)
160     {
161       __glibcxx_assert(__m != memory_order_acquire);
162       __glibcxx_assert(__m != memory_order_acq_rel);
163       __glibcxx_assert(__m != memory_order_consume);
164       _ATOMIC_STORE_(this, __v, __m);
165     }
166
167     void
168     store(void* __v, memory_order __m = memory_order_seq_cst) volatile
169     {
170       __glibcxx_assert(__m != memory_order_acquire);
171       __glibcxx_assert(__m != memory_order_acq_rel);
172       __glibcxx_assert(__m != memory_order_consume);
173       _ATOMIC_STORE_(this, __v, __m);
174     }
175
176     void*
177     load(memory_order __m = memory_order_seq_cst) const
178     {
179       __glibcxx_assert(__m != memory_order_release);
180       __glibcxx_assert(__m != memory_order_acq_rel);
181       return _ATOMIC_LOAD_(this, __m);
182     }
183
184     void*
185     load(memory_order __m = memory_order_seq_cst) const volatile
186     {
187       __glibcxx_assert(__m != memory_order_release);
188       __glibcxx_assert(__m != memory_order_acq_rel);
189       return _ATOMIC_LOAD_(this, __m);
190     }
191
192     void*
193     exchange(void* __v, memory_order __m = memory_order_seq_cst)
194     { return _ATOMIC_MODIFY_(this, =, __v, __m); }
195
196     void*
197     exchange(void* __v, memory_order __m = memory_order_seq_cst) volatile
198     { return _ATOMIC_MODIFY_(this, =, __v, __m); }
199
200     bool
201     compare_exchange_weak(void*& __v1, void* __v2, memory_order __m1,
202                           memory_order __m2)
203     {
204       __glibcxx_assert(__m2 != memory_order_release);
205       __glibcxx_assert(__m2 != memory_order_acq_rel);
206       __glibcxx_assert(__m2 <= __m1);
207       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
208     }
209
210     bool
211     compare_exchange_weak(void*& __v1, void* __v2, memory_order __m1,
212                           memory_order __m2) volatile
213     {
214       __glibcxx_assert(__m2 != memory_order_release);
215       __glibcxx_assert(__m2 != memory_order_acq_rel);
216       __glibcxx_assert(__m2 <= __m1);
217       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
218     }
219
220     bool
221     compare_exchange_weak(void*& __v1, void* __v2,
222                           memory_order __m = memory_order_seq_cst)
223     {
224       return compare_exchange_weak(__v1, __v2, __m,
225                                    __calculate_memory_order(__m));
226     }
227
228     bool
229     compare_exchange_weak(void*& __v1, void* __v2,
230                           memory_order __m = memory_order_seq_cst) volatile
231     {
232       return compare_exchange_weak(__v1, __v2, __m,
233                                    __calculate_memory_order(__m));
234     }
235
236     bool
237     compare_exchange_weak(const void*& __v1, const void* __v2,
238                           memory_order __m1, memory_order __m2)
239     {
240       __glibcxx_assert(__m2 != memory_order_release);
241       __glibcxx_assert(__m2 != memory_order_acq_rel);
242       __glibcxx_assert(__m2 <= __m1);
243       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
244     }
245
246     bool
247     compare_exchange_weak(const void*& __v1, const void* __v2,
248                           memory_order __m1, memory_order __m2) volatile
249     {
250       __glibcxx_assert(__m2 != memory_order_release);
251       __glibcxx_assert(__m2 != memory_order_acq_rel);
252       __glibcxx_assert(__m2 <= __m1);
253       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
254     }
255
256     bool
257     compare_exchange_weak(const void*& __v1, const void* __v2,
258                           memory_order __m = memory_order_seq_cst)
259     {
260       return compare_exchange_weak(__v1, __v2, __m,
261                                    __calculate_memory_order(__m));
262     }
263
264     bool
265     compare_exchange_weak(const void*& __v1, const void* __v2,
266                           memory_order __m = memory_order_seq_cst) volatile
267     {
268       return compare_exchange_weak(__v1, __v2, __m,
269                                    __calculate_memory_order(__m));
270     }
271
272     bool
273     compare_exchange_strong(void*& __v1, void* __v2, memory_order __m1,
274                             memory_order __m2)
275     {
276       __glibcxx_assert(__m2 != memory_order_release);
277       __glibcxx_assert(__m2 != memory_order_acq_rel);
278       __glibcxx_assert(__m2 <= __m1);
279       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
280     }
281
282     bool
283     compare_exchange_strong(void*& __v1, void* __v2, memory_order __m1,
284                             memory_order __m2) volatile
285     {
286       __glibcxx_assert(__m2 != memory_order_release);
287       __glibcxx_assert(__m2 != memory_order_acq_rel);
288       __glibcxx_assert(__m2 <= __m1);
289       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
290     }
291
292     bool
293     compare_exchange_strong(void*& __v1, void* __v2,
294                             memory_order __m = memory_order_seq_cst)
295     {
296       return compare_exchange_strong(__v1, __v2, __m,
297                                      __calculate_memory_order(__m));
298     }
299
300     bool
301     compare_exchange_strong(void*& __v1, void* __v2,
302                             memory_order __m = memory_order_seq_cst) volatile
303     {
304       return compare_exchange_strong(__v1, __v2, __m,
305                                      __calculate_memory_order(__m));
306     }
307
308     bool
309     compare_exchange_strong(const void*& __v1, const void* __v2,
310                             memory_order __m1, memory_order __m2)
311     {
312       __glibcxx_assert(__m2 != memory_order_release);
313       __glibcxx_assert(__m2 != memory_order_acq_rel);
314       __glibcxx_assert(__m2 <= __m1);
315       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
316     }
317
318     bool
319     compare_exchange_strong(const void*& __v1, const void* __v2,
320                             memory_order __m1, memory_order __m2) volatile
321     {
322       __glibcxx_assert(__m2 != memory_order_release);
323       __glibcxx_assert(__m2 != memory_order_acq_rel);
324       __glibcxx_assert(__m2 <= __m1);
325       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
326     }
327
328     bool
329     compare_exchange_strong(const void*& __v1, const void* __v2,
330                             memory_order __m = memory_order_seq_cst)
331     {
332       return compare_exchange_strong(__v1, __v2, __m,
333                                      __calculate_memory_order(__m));
334     }
335
336     bool
337     compare_exchange_strong(const void*& __v1, const void* __v2,
338                             memory_order __m = memory_order_seq_cst) volatile
339     {
340       return compare_exchange_strong(__v1, __v2, __m,
341                                      __calculate_memory_order(__m));
342     }
343
344     void*
345     fetch_add(ptrdiff_t __d, memory_order __m = memory_order_seq_cst)
346     {
347       void** __p = &(_M_i);
348       __atomic_flag_base* __g = __atomic_flag_for_address(__p);
349       __atomic_flag_wait_explicit(__g, __m);
350       void* __r = *__p;
351       *__p = (void*)((char*)(*__p) + __d);
352       atomic_flag_clear_explicit(__g, __m);
353       return __r;
354     }
355
356     void*
357     fetch_add(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile
358     {
359       void* volatile* __p = &(_M_i);
360       __atomic_flag_base* __g = __atomic_flag_for_address(__p);
361       __atomic_flag_wait_explicit(__g, __m);
362       void* __r = *__p;
363       *__p = (void*)((char*)(*__p) + __d);
364       atomic_flag_clear_explicit(__g, __m);
365       return __r;
366     }
367
368     void*
369     fetch_sub(ptrdiff_t __d, memory_order __m = memory_order_seq_cst)
370     {
371       void** __p = &(_M_i);
372       __atomic_flag_base* __g = __atomic_flag_for_address(__p);
373       __atomic_flag_wait_explicit(__g, __m);
374       void* __r = *__p;
375       *__p = (void*)((char*)(*__p) - __d);
376       atomic_flag_clear_explicit(__g, __m);
377       return __r;
378     }
379
380     void*
381     fetch_sub(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile
382     {
383       void* volatile* __p = &(_M_i);
384       __atomic_flag_base* __g = __atomic_flag_for_address(__p);
385       __atomic_flag_wait_explicit(__g, __m);
386       void* __r = *__p;
387       *__p = (void*)((char*)(*__p) - __d);
388       atomic_flag_clear_explicit(__g, __m);
389       return __r;
390     }
391
392     operator void*() const
393     { return load(); }
394
395     operator void*() const volatile
396     { return load(); }
397
398     // XXX
399     void*
400     operator=(void* __v)
401     {
402       store(__v);
403       return __v;
404     }
405
406     void*
407     operator=(void* __v) volatile
408     {
409       store(__v);
410       return __v;
411     }
412
413     void*
414     operator+=(ptrdiff_t __d)
415     { return fetch_add(__d) + __d; }
416
417     void*
418     operator+=(ptrdiff_t __d) volatile
419     { return fetch_add(__d) + __d; }
420
421     void*
422     operator-=(ptrdiff_t __d)
423     { return fetch_sub(__d) - __d; }
424
425     void*
426     operator-=(ptrdiff_t __d) volatile
427     { return fetch_sub(__d) - __d; }
428   };
429
430
431   /// Base class for atomic integrals.
432   //
433   // For each of the integral types, define atomic_[integral type] struct
434   //
435   // atomic_bool     bool
436   // atomic_char     char
437   // atomic_schar    signed char
438   // atomic_uchar    unsigned char
439   // atomic_short    short
440   // atomic_ushort   unsigned short
441   // atomic_int      int
442   // atomic_uint     unsigned int
443   // atomic_long     long
444   // atomic_ulong    unsigned long
445   // atomic_llong    long long
446   // atomic_ullong   unsigned long long
447   // atomic_char16_t char16_t
448   // atomic_char32_t char32_t
449   // atomic_wchar_t  wchar_t
450
451   // Base type.
452   // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or 8 bytes,
453   // since that is what GCC built-in functions for atomic memory access work on.
454   template<typename _ITp>
455     struct __atomic_base
456     {
457     private:
458       typedef _ITp      __int_type;
459
460       __int_type        _M_i;
461
462     public:
463       __atomic_base() = default;
464       ~__atomic_base() = default;
465       __atomic_base(const __atomic_base&) = delete;
466       __atomic_base& operator=(const __atomic_base&) = delete;
467       __atomic_base& operator=(const __atomic_base&) volatile = delete;
468
469       // Requires __int_type convertible to _M_base._M_i.
470       constexpr __atomic_base(__int_type __i): _M_i (__i) { }
471
472       operator __int_type() const
473       { return load(); }
474
475       operator __int_type() const volatile
476       { return load(); }
477
478       __int_type
479       operator=(__int_type __i)
480       {
481         store(__i);
482         return __i;
483       }
484
485       __int_type
486       operator=(__int_type __i) volatile
487       {
488         store(__i);
489         return __i;
490       }
491
492       __int_type
493       operator++(int)
494       { return fetch_add(1); }
495
496       __int_type
497       operator++(int) volatile
498       { return fetch_add(1); }
499
500       __int_type
501       operator--(int)
502       { return fetch_sub(1); }
503
504       __int_type
505       operator--(int) volatile
506       { return fetch_sub(1); }
507
508       __int_type
509       operator++()
510       { return fetch_add(1) + 1; }
511
512       __int_type
513       operator++() volatile
514       { return fetch_add(1) + 1; }
515
516       __int_type
517       operator--()
518       { return fetch_sub(1) - 1; }
519
520       __int_type
521       operator--() volatile
522       { return fetch_sub(1) - 1; }
523
524       __int_type
525       operator+=(__int_type __i)
526       { return fetch_add(__i) + __i; }
527
528       __int_type
529       operator+=(__int_type __i) volatile
530       { return fetch_add(__i) + __i; }
531
532       __int_type
533       operator-=(__int_type __i)
534       { return fetch_sub(__i) - __i; }
535
536       __int_type
537       operator-=(__int_type __i) volatile
538       { return fetch_sub(__i) - __i; }
539
540       __int_type
541       operator&=(__int_type __i)
542       { return fetch_and(__i) & __i; }
543
544       __int_type
545       operator&=(__int_type __i) volatile
546       { return fetch_and(__i) & __i; }
547
548       __int_type
549       operator|=(__int_type __i)
550       { return fetch_or(__i) | __i; }
551
552       __int_type
553       operator|=(__int_type __i) volatile
554       { return fetch_or(__i) | __i; }
555
556       __int_type
557       operator^=(__int_type __i)
558       { return fetch_xor(__i) ^ __i; }
559
560       __int_type
561       operator^=(__int_type __i) volatile
562       { return fetch_xor(__i) ^ __i; }
563
564       bool
565       is_lock_free() const
566       { return false; }
567
568       bool
569       is_lock_free() const volatile
570       { return false; }
571
572       void
573       store(__int_type __i, memory_order __m = memory_order_seq_cst)
574       {
575         __glibcxx_assert(__m != memory_order_acquire);
576         __glibcxx_assert(__m != memory_order_acq_rel);
577         __glibcxx_assert(__m != memory_order_consume);
578         _ATOMIC_STORE_(this, __i, __m);
579       }
580
581       void
582       store(__int_type __i, memory_order __m = memory_order_seq_cst) volatile
583       {
584         __glibcxx_assert(__m != memory_order_acquire);
585         __glibcxx_assert(__m != memory_order_acq_rel);
586         __glibcxx_assert(__m != memory_order_consume);
587         _ATOMIC_STORE_(this, __i, __m);
588       }
589
590       __int_type
591       load(memory_order __m = memory_order_seq_cst) const
592       {
593         __glibcxx_assert(__m != memory_order_release);
594         __glibcxx_assert(__m != memory_order_acq_rel);
595         return _ATOMIC_LOAD_(this, __m);
596       }
597
598       __int_type
599       load(memory_order __m = memory_order_seq_cst) const volatile
600       {
601         __glibcxx_assert(__m != memory_order_release);
602         __glibcxx_assert(__m != memory_order_acq_rel);
603         return _ATOMIC_LOAD_(this, __m);
604       }
605
606       __int_type
607       exchange(__int_type __i, memory_order __m = memory_order_seq_cst)
608       { return _ATOMIC_MODIFY_(this, =, __i, __m); }
609
610       __int_type
611       exchange(__int_type __i, memory_order __m = memory_order_seq_cst) volatile
612       { return _ATOMIC_MODIFY_(this, =, __i, __m); }
613
614       bool
615       compare_exchange_weak(__int_type& __i1, __int_type __i2,
616                             memory_order __m1, memory_order __m2)
617       {
618         __glibcxx_assert(__m2 != memory_order_release);
619         __glibcxx_assert(__m2 != memory_order_acq_rel);
620         __glibcxx_assert(__m2 <= __m1);
621         return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
622       }
623
624       bool
625       compare_exchange_weak(__int_type& __i1, __int_type __i2,
626                             memory_order __m1, memory_order __m2) volatile
627       {
628         __glibcxx_assert(__m2 != memory_order_release);
629         __glibcxx_assert(__m2 != memory_order_acq_rel);
630         __glibcxx_assert(__m2 <= __m1);
631         return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
632       }
633
634       bool
635       compare_exchange_weak(__int_type& __i1, __int_type __i2,
636                             memory_order __m = memory_order_seq_cst)
637       {
638         return compare_exchange_weak(__i1, __i2, __m,
639                                      __calculate_memory_order(__m));
640       }
641
642       bool
643       compare_exchange_weak(__int_type& __i1, __int_type __i2,
644                             memory_order __m = memory_order_seq_cst) volatile
645       {
646         return compare_exchange_weak(__i1, __i2, __m,
647                                      __calculate_memory_order(__m));
648       }
649
650       bool
651       compare_exchange_strong(__int_type& __i1, __int_type __i2,
652                               memory_order __m1, memory_order __m2)
653       {
654         __glibcxx_assert(__m2 != memory_order_release);
655         __glibcxx_assert(__m2 != memory_order_acq_rel);
656         __glibcxx_assert(__m2 <= __m1);
657         return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
658       }
659
660       bool
661       compare_exchange_strong(__int_type& __i1, __int_type __i2,
662                               memory_order __m1, memory_order __m2) volatile
663       {
664         __glibcxx_assert(__m2 != memory_order_release);
665         __glibcxx_assert(__m2 != memory_order_acq_rel);
666         __glibcxx_assert(__m2 <= __m1);
667         return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
668       }
669
670       bool
671       compare_exchange_strong(__int_type& __i1, __int_type __i2,
672                               memory_order __m = memory_order_seq_cst)
673       {
674         return compare_exchange_strong(__i1, __i2, __m,
675                                        __calculate_memory_order(__m));
676       }
677
678       bool
679       compare_exchange_strong(__int_type& __i1, __int_type __i2,
680                               memory_order __m = memory_order_seq_cst) volatile
681       {
682         return compare_exchange_strong(__i1, __i2, __m,
683                                        __calculate_memory_order(__m));
684       }
685
686       __int_type
687       fetch_add(__int_type __i, memory_order __m = memory_order_seq_cst)
688       { return _ATOMIC_MODIFY_(this, +=, __i, __m); }
689
690       __int_type
691       fetch_add(__int_type __i,
692                 memory_order __m = memory_order_seq_cst) volatile
693       { return _ATOMIC_MODIFY_(this, +=, __i, __m); }
694
695       __int_type
696       fetch_sub(__int_type __i, memory_order __m = memory_order_seq_cst)
697       { return _ATOMIC_MODIFY_(this, -=, __i, __m); }
698
699       __int_type
700       fetch_sub(__int_type __i,
701                 memory_order __m = memory_order_seq_cst) volatile
702       { return _ATOMIC_MODIFY_(this, -=, __i, __m); }
703
704       __int_type
705       fetch_and(__int_type __i, memory_order __m = memory_order_seq_cst)
706       { return _ATOMIC_MODIFY_(this, &=, __i, __m); }
707
708       __int_type
709       fetch_and(__int_type __i,
710                 memory_order __m = memory_order_seq_cst) volatile
711       { return _ATOMIC_MODIFY_(this, &=, __i, __m); }
712
713       __int_type
714       fetch_or(__int_type __i, memory_order __m = memory_order_seq_cst)
715       { return _ATOMIC_MODIFY_(this, |=, __i, __m); }
716
717       __int_type
718       fetch_or(__int_type __i, memory_order __m = memory_order_seq_cst) volatile
719       { return _ATOMIC_MODIFY_(this, |=, __i, __m); }
720
721       __int_type
722       fetch_xor(__int_type __i, memory_order __m = memory_order_seq_cst)
723       { return _ATOMIC_MODIFY_(this, ^=, __i, __m); }
724
725       __int_type
726       fetch_xor(__int_type __i,
727                 memory_order __m = memory_order_seq_cst) volatile
728       { return _ATOMIC_MODIFY_(this, ^=, __i, __m); }
729     };
730
731 #undef _ATOMIC_LOAD_
732 #undef _ATOMIC_STORE_
733 #undef _ATOMIC_MODIFY_
734 #undef _ATOMIC_CMPEXCHNG_
735 } // namespace __atomic0
736
737 _GLIBCXX_END_NAMESPACE_VERSION
738 } // namespace
739
740 #endif