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