OSDN Git Service

* include/std/chrono: Extend constexpr application.
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / atomic_2.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_2.h
27  *  This is an internal header file, included by other library headers.
28  *  You should not attempt to use it directly.
29  */
30
31 #ifndef _GLIBCXX_ATOMIC_2_H
32 #define _GLIBCXX_ATOMIC_2_H 1
33
34 #pragma GCC system_header
35
36 _GLIBCXX_BEGIN_NAMESPACE(std)
37
38 // 2 == __atomic2 == Always lock-free
39 // Assumed:
40 // _GLIBCXX_ATOMIC_BUILTINS_1
41 // _GLIBCXX_ATOMIC_BUILTINS_2
42 // _GLIBCXX_ATOMIC_BUILTINS_4
43 // _GLIBCXX_ATOMIC_BUILTINS_8
44 namespace __atomic2
45 {
46   /// atomic_flag
47   struct atomic_flag : public __atomic_flag_base
48   {
49     atomic_flag() = default;
50     ~atomic_flag() = default;
51     atomic_flag(const atomic_flag&) = delete;
52     atomic_flag& operator=(const atomic_flag&) = delete;
53     atomic_flag& operator=(const atomic_flag&) volatile = delete;
54
55     // Conversion to ATOMIC_FLAG_INIT.
56     atomic_flag(bool __i): __atomic_flag_base({ __i }) { }
57
58     bool
59     test_and_set(memory_order __m = memory_order_seq_cst)
60     {
61       // Redundant synchronize if built-in for lock is a full barrier.
62       if (__m != memory_order_acquire && __m != memory_order_acq_rel)
63         __sync_synchronize();
64       return __sync_lock_test_and_set(&_M_i, 1);
65     }
66
67     bool
68     test_and_set(memory_order __m = memory_order_seq_cst) volatile
69     {
70       // Redundant synchronize if built-in for lock is a full barrier.
71       if (__m != memory_order_acquire && __m != memory_order_acq_rel)
72         __sync_synchronize();
73       return __sync_lock_test_and_set(&_M_i, 1);
74     }
75
76     void
77     clear(memory_order __m = memory_order_seq_cst)
78     {
79       __glibcxx_assert(__m != memory_order_consume);
80       __glibcxx_assert(__m != memory_order_acquire);
81       __glibcxx_assert(__m != memory_order_acq_rel);
82
83       __sync_lock_release(&_M_i);
84       if (__m != memory_order_acquire && __m != memory_order_acq_rel)
85         __sync_synchronize();
86     }
87
88     void
89     clear(memory_order __m = memory_order_seq_cst) volatile
90     {
91       __glibcxx_assert(__m != memory_order_consume);
92       __glibcxx_assert(__m != memory_order_acquire);
93       __glibcxx_assert(__m != memory_order_acq_rel);
94
95       __sync_lock_release(&_M_i);
96       if (__m != memory_order_acquire && __m != memory_order_acq_rel)
97         __sync_synchronize();
98     }
99   };
100
101
102   /// atomic_address
103   struct atomic_address
104   {
105   private:
106     void* _M_i;
107
108   public:
109     atomic_address() = default;
110     ~atomic_address() = default;
111     atomic_address(const atomic_address&) = delete;
112     atomic_address& operator=(const atomic_address&) = delete;
113     atomic_address& operator=(const atomic_address&) volatile = delete;
114
115     constexpr atomic_address(void* __v): _M_i (__v) {  }
116
117     bool
118     is_lock_free() const { return true; }
119
120     bool
121     is_lock_free() const volatile { return true; }
122
123     void
124     store(void* __v, memory_order __m = memory_order_seq_cst)
125     {
126       __glibcxx_assert(__m != memory_order_acquire);
127       __glibcxx_assert(__m != memory_order_acq_rel);
128       __glibcxx_assert(__m != memory_order_consume);
129
130       if (__m == memory_order_relaxed)
131         _M_i = __v;
132       else
133         {
134           // write_mem_barrier();
135           _M_i = __v;
136           if (__m == memory_order_seq_cst)
137             __sync_synchronize();
138         }
139     }
140
141     void
142     store(void* __v, memory_order __m = memory_order_seq_cst) volatile
143     {
144       __glibcxx_assert(__m != memory_order_acquire);
145       __glibcxx_assert(__m != memory_order_acq_rel);
146       __glibcxx_assert(__m != memory_order_consume);
147
148       if (__m == memory_order_relaxed)
149         _M_i = __v;
150       else
151         {
152           // write_mem_barrier();
153           _M_i = __v;
154           if (__m == memory_order_seq_cst)
155             __sync_synchronize();
156         }
157     }
158
159     void*
160     load(memory_order __m = memory_order_seq_cst) const
161     {
162       __glibcxx_assert(__m != memory_order_release);
163       __glibcxx_assert(__m != memory_order_acq_rel);
164
165       __sync_synchronize();
166       void* __ret = _M_i;
167       __sync_synchronize();
168       return __ret;
169     }
170
171     void*
172     load(memory_order __m = memory_order_seq_cst) const volatile
173     {
174       __glibcxx_assert(__m != memory_order_release);
175       __glibcxx_assert(__m != memory_order_acq_rel);
176
177       __sync_synchronize();
178       void* __ret = _M_i;
179       __sync_synchronize();
180       return __ret;
181     }
182
183     void*
184     exchange(void* __v, memory_order __m = memory_order_seq_cst)
185     {
186       // XXX built-in assumes memory_order_acquire.
187       return __sync_lock_test_and_set(&_M_i, __v);
188     }
189
190     void*
191     exchange(void* __v, memory_order __m = memory_order_seq_cst) volatile
192     {
193       // XXX built-in assumes memory_order_acquire.
194       return __sync_lock_test_and_set(&_M_i, __v);
195     }
196
197     bool
198     compare_exchange_weak(void*& __v1, void* __v2, memory_order __m1,
199                           memory_order __m2)
200     { return compare_exchange_strong(__v1, __v2, __m1, __m2); }
201
202     bool
203     compare_exchange_weak(void*& __v1, void* __v2, memory_order __m1,
204                           memory_order __m2) volatile
205     { return compare_exchange_strong(__v1, __v2, __m1, __m2); }
206
207     bool
208     compare_exchange_weak(void*& __v1, void* __v2,
209                           memory_order __m = memory_order_seq_cst)
210     {
211       return compare_exchange_weak(__v1, __v2, __m,
212                                    __calculate_memory_order(__m));
213     }
214
215     bool
216     compare_exchange_weak(void*& __v1, void* __v2,
217                           memory_order __m = memory_order_seq_cst) volatile
218     {
219       return compare_exchange_weak(__v1, __v2, __m,
220                                    __calculate_memory_order(__m));
221     }
222
223     bool
224     compare_exchange_weak(const void*& __v1, const void* __v2,
225                           memory_order __m1, memory_order __m2)
226     { return compare_exchange_strong(__v1, __v2, __m1, __m2); }
227
228     bool
229     compare_exchange_weak(const void*& __v1, const void* __v2,
230                           memory_order __m1, memory_order __m2) volatile
231     { return compare_exchange_strong(__v1, __v2, __m1, __m2); }
232
233     bool
234     compare_exchange_weak(const void*& __v1, const void* __v2,
235                           memory_order __m = memory_order_seq_cst)
236     {
237       return compare_exchange_weak(__v1, __v2, __m,
238                                    __calculate_memory_order(__m));
239     }
240
241     bool
242     compare_exchange_weak(const void*& __v1, const void* __v2,
243                           memory_order __m = memory_order_seq_cst) volatile
244     {
245       return compare_exchange_weak(__v1, __v2, __m,
246                                    __calculate_memory_order(__m));
247     }
248
249     bool
250     compare_exchange_strong(void*& __v1, void* __v2, memory_order __m1,
251                             memory_order __m2)
252     {
253       __glibcxx_assert(__m2 != memory_order_release);
254       __glibcxx_assert(__m2 != memory_order_acq_rel);
255       __glibcxx_assert(__m2 <= __m1);
256
257       void* __v1o = __v1;
258       void* __v1n = __sync_val_compare_and_swap(&_M_i, __v1o, __v2);
259
260       // Assume extra stores (of same value) allowed in true case.
261       __v1 = __v1n;
262       return __v1o == __v1n;
263     }
264
265     bool
266     compare_exchange_strong(void*& __v1, void* __v2, memory_order __m1,
267                             memory_order __m2) volatile
268     {
269       __glibcxx_assert(__m2 != memory_order_release);
270       __glibcxx_assert(__m2 != memory_order_acq_rel);
271       __glibcxx_assert(__m2 <= __m1);
272
273       void* __v1o = __v1;
274       void* __v1n = __sync_val_compare_and_swap(&_M_i, __v1o, __v2);
275
276       // Assume extra stores (of same value) allowed in true case.
277       __v1 = __v1n;
278       return __v1o == __v1n;
279     }
280
281     bool
282     compare_exchange_strong(void*& __v1, void* __v2,
283                             memory_order __m = memory_order_seq_cst)
284     {
285       return compare_exchange_strong(__v1, __v2, __m,
286                                      __calculate_memory_order(__m));
287     }
288
289     bool
290     compare_exchange_strong(void*& __v1, void* __v2,
291                             memory_order __m = memory_order_seq_cst) volatile
292     {
293       return compare_exchange_strong(__v1, __v2, __m,
294                                      __calculate_memory_order(__m));
295     }
296
297     bool
298     compare_exchange_strong(const void*& __v1, const void* __v2,
299                             memory_order __m1, memory_order __m2)
300     {
301       __glibcxx_assert(__m2 != memory_order_release);
302       __glibcxx_assert(__m2 != memory_order_acq_rel);
303       __glibcxx_assert(__m2 <= __m1);
304
305       const void* __v1o = __v1;
306       const void* __v1n = __sync_val_compare_and_swap(&_M_i, __v1o, __v2);
307
308       // Assume extra stores (of same value) allowed in true case.
309       __v1 = __v1n;
310       return __v1o == __v1n;
311     }
312
313     bool
314     compare_exchange_strong(const void*& __v1, const void* __v2,
315                             memory_order __m1, memory_order __m2) volatile
316     {
317       __glibcxx_assert(__m2 != memory_order_release);
318       __glibcxx_assert(__m2 != memory_order_acq_rel);
319       __glibcxx_assert(__m2 <= __m1);
320
321       const void* __v1o = __v1;
322       const void* __v1n = __sync_val_compare_and_swap(&_M_i, __v1o, __v2);
323
324       // Assume extra stores (of same value) allowed in true case.
325       __v1 = __v1n;
326       return __v1o == __v1n;
327     }
328
329     bool
330     compare_exchange_strong(const void*& __v1, const void* __v2,
331                             memory_order __m = memory_order_seq_cst)
332     {
333       return compare_exchange_strong(__v1, __v2, __m,
334                                      __calculate_memory_order(__m));
335     }
336
337     bool
338     compare_exchange_strong(const void*& __v1, const void* __v2,
339                             memory_order __m = memory_order_seq_cst) volatile
340     {
341       return compare_exchange_strong(__v1, __v2, __m,
342                                      __calculate_memory_order(__m));
343     }
344
345     void*
346     fetch_add(ptrdiff_t __d, memory_order __m = memory_order_seq_cst)
347     { return __sync_fetch_and_add(&_M_i, __d); }
348
349     void*
350     fetch_add(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile
351     { return __sync_fetch_and_add(&_M_i, __d); }
352
353     void*
354     fetch_sub(ptrdiff_t __d, memory_order __m = memory_order_seq_cst)
355     { return __sync_fetch_and_sub(&_M_i, __d); }
356
357     void*
358     fetch_sub(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile
359     { return __sync_fetch_and_sub(&_M_i, __d); }
360
361     operator void*() const
362     { return load(); }
363
364     operator void*() const volatile
365     { return load(); }
366
367     void*
368 #if 0
369     // XXX as specified but won't compile as store takes void*,
370     // invalid conversion from const void* to void*
371     // CD1 had this signature
372     operator=(const void* __v)
373 #else
374     operator=(void* __v)      
375 #endif
376     {
377       store(__v);
378       return __v;
379     }
380
381     void*
382 #if 0
383     // XXX as specified but won't compile as store takes void*,
384     // invalid conversion from const void* to void*
385     // CD1 had this signature, but store and this could both be const void*?
386     operator=(const void* __v) volatile
387 #else
388     operator=(void* __v) volatile
389 #endif
390     {
391       store(__v);
392       return __v;
393     }
394
395     void*
396     operator+=(ptrdiff_t __d)
397     { return __sync_add_and_fetch(&_M_i, __d); }
398
399     void*
400     operator+=(ptrdiff_t __d) volatile
401     { return __sync_add_and_fetch(&_M_i, __d); }
402
403     void*
404     operator-=(ptrdiff_t __d)
405     { return __sync_sub_and_fetch(&_M_i, __d); }
406
407     void*
408     operator-=(ptrdiff_t __d) volatile
409     { return __sync_sub_and_fetch(&_M_i, __d); }
410   };
411
412
413   /// Base class for atomic integrals.
414   //
415   // For each of the integral types, define atomic_[integral type] struct
416   //
417   // atomic_bool     bool
418   // atomic_char     char
419   // atomic_schar    signed char
420   // atomic_uchar    unsigned char
421   // atomic_short    short
422   // atomic_ushort   unsigned short
423   // atomic_int      int
424   // atomic_uint     unsigned int
425   // atomic_long     long
426   // atomic_ulong    unsigned long
427   // atomic_llong    long long
428   // atomic_ullong   unsigned long long
429   // atomic_char16_t char16_t
430   // atomic_char32_t char32_t
431   // atomic_wchar_t  wchar_t
432   //
433   // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or
434   // 8 bytes, since that is what GCC built-in functions for atomic
435   // memory access expect.
436   template<typename _ITp>
437     struct __atomic_base
438     {
439     private:
440       typedef _ITp      __int_type;
441
442       __int_type        _M_i;
443
444     public:
445       __atomic_base() = default;
446       ~__atomic_base() = default;
447       __atomic_base(const __atomic_base&) = delete;
448       __atomic_base& operator=(const __atomic_base&) = delete;
449       __atomic_base& operator=(const __atomic_base&) volatile = delete;
450
451       // Requires __int_type convertible to _M_i.
452       constexpr __atomic_base(__int_type __i): _M_i (__i) { }
453
454       operator __int_type() const
455       { return load(); }
456
457       operator __int_type() const volatile
458       { return load(); }
459
460       __int_type
461       operator=(__int_type __i)
462       {
463         store(__i);
464         return __i;
465       }
466
467       __int_type
468       operator=(__int_type __i) volatile
469       {
470         store(__i);
471         return __i;
472       }
473
474       __int_type
475       operator++(int)
476       { return fetch_add(1); }
477
478       __int_type
479       operator++(int) volatile
480       { return fetch_add(1); }
481
482       __int_type
483       operator--(int)
484       { return fetch_sub(1); }
485
486       __int_type
487       operator--(int) volatile
488       { return fetch_sub(1); }
489
490       __int_type
491       operator++()
492       { return __sync_add_and_fetch(&_M_i, 1); }
493
494       __int_type
495       operator++() volatile
496       { return __sync_add_and_fetch(&_M_i, 1); }
497
498       __int_type
499       operator--()
500       { return __sync_sub_and_fetch(&_M_i, 1); }
501
502       __int_type
503       operator--() volatile
504       { return __sync_sub_and_fetch(&_M_i, 1); }
505
506       __int_type
507       operator+=(__int_type __i)
508       { return __sync_add_and_fetch(&_M_i, __i); }
509
510       __int_type
511       operator+=(__int_type __i) volatile
512       { return __sync_add_and_fetch(&_M_i, __i); }
513
514       __int_type
515       operator-=(__int_type __i)
516       { return __sync_sub_and_fetch(&_M_i, __i); }
517
518       __int_type
519       operator-=(__int_type __i) volatile
520       { return __sync_sub_and_fetch(&_M_i, __i); }
521
522       __int_type
523       operator&=(__int_type __i)
524       { return __sync_and_and_fetch(&_M_i, __i); }
525
526       __int_type
527       operator&=(__int_type __i) volatile
528       { return __sync_and_and_fetch(&_M_i, __i); }
529
530       __int_type
531       operator|=(__int_type __i)
532       { return __sync_or_and_fetch(&_M_i, __i); }
533
534       __int_type
535       operator|=(__int_type __i) volatile
536       { return __sync_or_and_fetch(&_M_i, __i); }
537
538       __int_type
539       operator^=(__int_type __i)
540       { return __sync_xor_and_fetch(&_M_i, __i); }
541
542       __int_type
543       operator^=(__int_type __i) volatile
544       { return __sync_xor_and_fetch(&_M_i, __i); }
545
546       bool
547       is_lock_free() const
548       { return true; }
549
550       bool
551       is_lock_free() const volatile
552       { return true; }
553
554       void
555       store(__int_type __i, memory_order __m = memory_order_seq_cst)
556       {
557         __glibcxx_assert(__m != memory_order_acquire);
558         __glibcxx_assert(__m != memory_order_acq_rel);
559         __glibcxx_assert(__m != memory_order_consume);
560
561         if (__m == memory_order_relaxed)
562           _M_i = __i;
563         else
564           {
565             // write_mem_barrier();
566             _M_i = __i;
567             if (__m == memory_order_seq_cst)
568               __sync_synchronize();
569           }
570       }
571
572       void
573       store(__int_type __i, memory_order __m = memory_order_seq_cst) volatile
574       {
575         __glibcxx_assert(__m != memory_order_acquire);
576         __glibcxx_assert(__m != memory_order_acq_rel);
577         __glibcxx_assert(__m != memory_order_consume);
578
579         if (__m == memory_order_relaxed)
580           _M_i = __i;
581         else
582           {
583             // write_mem_barrier();
584             _M_i = __i;
585             if (__m == memory_order_seq_cst)
586               __sync_synchronize();
587           }
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
596         __sync_synchronize();
597         __int_type __ret = _M_i;
598         __sync_synchronize();
599         return __ret;
600       }
601
602       __int_type
603       load(memory_order __m = memory_order_seq_cst) const volatile
604       {
605         __glibcxx_assert(__m != memory_order_release);
606         __glibcxx_assert(__m != memory_order_acq_rel);
607
608         __sync_synchronize();
609         __int_type __ret = _M_i;
610         __sync_synchronize();
611         return __ret;
612       }
613
614       __int_type
615       exchange(__int_type __i, memory_order __m = memory_order_seq_cst)
616       {
617         // XXX built-in assumes memory_order_acquire.
618         return __sync_lock_test_and_set(&_M_i, __i);
619       }
620
621
622       __int_type
623       exchange(__int_type __i, memory_order __m = memory_order_seq_cst) volatile
624       {
625         // XXX built-in assumes memory_order_acquire.
626         return __sync_lock_test_and_set(&_M_i, __i);
627       }
628
629       bool
630       compare_exchange_weak(__int_type& __i1, __int_type __i2,
631                             memory_order __m1, memory_order __m2)
632       { return compare_exchange_strong(__i1, __i2, __m1, __m2); }
633
634       bool
635       compare_exchange_weak(__int_type& __i1, __int_type __i2,
636                             memory_order __m1, memory_order __m2) volatile
637       { return compare_exchange_strong(__i1, __i2, __m1, __m2); }
638
639       bool
640       compare_exchange_weak(__int_type& __i1, __int_type __i2,
641                             memory_order __m = memory_order_seq_cst)
642       {
643         return compare_exchange_weak(__i1, __i2, __m,
644                                      __calculate_memory_order(__m));
645       }
646
647       bool
648       compare_exchange_weak(__int_type& __i1, __int_type __i2,
649                             memory_order __m = memory_order_seq_cst) volatile
650       {
651         return compare_exchange_weak(__i1, __i2, __m,
652                                      __calculate_memory_order(__m));
653       }
654
655       bool
656       compare_exchange_strong(__int_type& __i1, __int_type __i2,
657                               memory_order __m1, memory_order __m2)
658       {
659         __glibcxx_assert(__m2 != memory_order_release);
660         __glibcxx_assert(__m2 != memory_order_acq_rel);
661         __glibcxx_assert(__m2 <= __m1);
662
663         __int_type __i1o = __i1;
664         __int_type __i1n = __sync_val_compare_and_swap(&_M_i, __i1o, __i2);
665
666         // Assume extra stores (of same value) allowed in true case.
667         __i1 = __i1n;
668         return __i1o == __i1n;
669       }
670
671       bool
672       compare_exchange_strong(__int_type& __i1, __int_type __i2,
673                               memory_order __m1, memory_order __m2) volatile
674       {
675         __glibcxx_assert(__m2 != memory_order_release);
676         __glibcxx_assert(__m2 != memory_order_acq_rel);
677         __glibcxx_assert(__m2 <= __m1);
678
679         __int_type __i1o = __i1;
680         __int_type __i1n = __sync_val_compare_and_swap(&_M_i, __i1o, __i2);
681
682         // Assume extra stores (of same value) allowed in true case.
683         __i1 = __i1n;
684         return __i1o == __i1n;
685       }
686
687       bool
688       compare_exchange_strong(__int_type& __i1, __int_type __i2,
689                               memory_order __m = memory_order_seq_cst)
690       {
691         return compare_exchange_strong(__i1, __i2, __m,
692                                        __calculate_memory_order(__m));
693       }
694
695       bool
696       compare_exchange_strong(__int_type& __i1, __int_type __i2,
697                               memory_order __m = memory_order_seq_cst) volatile
698       {
699         return compare_exchange_strong(__i1, __i2, __m,
700                                        __calculate_memory_order(__m));
701       }
702
703       __int_type
704       fetch_add(__int_type __i, memory_order __m = memory_order_seq_cst)
705       { return __sync_fetch_and_add(&_M_i, __i); }
706
707       __int_type
708       fetch_add(__int_type __i,
709                 memory_order __m = memory_order_seq_cst) volatile
710       { return __sync_fetch_and_add(&_M_i, __i); }
711
712       __int_type
713       fetch_sub(__int_type __i, memory_order __m = memory_order_seq_cst)
714       { return __sync_fetch_and_sub(&_M_i, __i); }
715
716       __int_type
717       fetch_sub(__int_type __i,
718                 memory_order __m = memory_order_seq_cst) volatile
719       { return __sync_fetch_and_sub(&_M_i, __i); }
720
721       __int_type
722       fetch_and(__int_type __i, memory_order __m = memory_order_seq_cst)
723       { return __sync_fetch_and_and(&_M_i, __i); }
724
725       __int_type
726       fetch_and(__int_type __i,
727                 memory_order __m = memory_order_seq_cst) volatile
728       { return __sync_fetch_and_and(&_M_i, __i); }
729
730       __int_type
731       fetch_or(__int_type __i, memory_order __m = memory_order_seq_cst)
732       { return __sync_fetch_and_or(&_M_i, __i); }
733
734       __int_type
735       fetch_or(__int_type __i,
736                memory_order __m = memory_order_seq_cst) volatile
737       { return __sync_fetch_and_or(&_M_i, __i); }
738
739       __int_type
740       fetch_xor(__int_type __i, memory_order __m = memory_order_seq_cst)
741       { return __sync_fetch_and_xor(&_M_i, __i); }
742
743       __int_type
744       fetch_xor(__int_type __i,
745                 memory_order __m = memory_order_seq_cst) volatile
746       { return __sync_fetch_and_xor(&_M_i, __i); }
747     };
748 } // namespace __atomic2
749
750 _GLIBCXX_END_NAMESPACE
751
752 #endif