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
44namespace 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) const { return __d * sizeof(_PTp); }
679
680      constexpr ptrdiff_t
681      _M_type_size(ptrdiff_t __d) const 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
893