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
40namespace 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