libstdc++
atomic
Go to the documentation of this file.
1// -*- C++ -*- header.
2
3// Copyright (C) 2008-2026 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 include/atomic
26 * This is a Standard C++ Library header.
27 */
28
29// Based on "C++ Atomic Types and Operations" by Hans Boehm and Lawrence Crowl.
30// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html
31
32#ifndef _GLIBCXX_ATOMIC
33#define _GLIBCXX_ATOMIC 1
34
35#ifdef _GLIBCXX_SYSHDR
36#pragma GCC system_header
37#endif
38
39#if __cplusplus < 201103L
40# include <bits/c++0x_warning.h>
41#else
42
43#define __glibcxx_want_atomic_is_always_lock_free
44#define __glibcxx_want_atomic_flag_test
45#define __glibcxx_want_atomic_float
46#define __glibcxx_want_atomic_min_max
47#define __glibcxx_want_atomic_ref
48#define __glibcxx_want_atomic_lock_free_type_aliases
49#define __glibcxx_want_atomic_value_initialization
50#define __glibcxx_want_atomic_wait
51#include <bits/version.h>
52
53#include <bits/atomic_base.h>
54#include <cstdint>
55#include <type_traits>
56
57namespace std _GLIBCXX_VISIBILITY(default)
58{
59_GLIBCXX_BEGIN_NAMESPACE_VERSION
60
61 /**
62 * @addtogroup atomics
63 * @{
64 */
65
66 template<typename _Tp>
67 struct atomic;
68
69 /// atomic<bool>
70 // NB: No operators or fetch-operations for this type.
71 template<>
72 struct atomic<bool>
73 {
74 using value_type = bool;
75
76 private:
77 __atomic_base<bool> _M_base;
78
79 public:
80 atomic() noexcept = default;
81 ~atomic() noexcept = default;
82 atomic(const atomic&) = delete;
83 atomic& operator=(const atomic&) = delete;
84 atomic& operator=(const atomic&) volatile = delete;
85
86 constexpr atomic(bool __i) noexcept : _M_base(__i) { }
87
88 bool
89 operator=(bool __i) noexcept
90 { return _M_base.operator=(__i); }
91
92 bool
93 operator=(bool __i) volatile noexcept
94 { return _M_base.operator=(__i); }
95
96 operator bool() const noexcept
97 { return _M_base.load(); }
98
99 operator bool() const volatile noexcept
100 { return _M_base.load(); }
101
102 bool
103 is_lock_free() const noexcept { return _M_base.is_lock_free(); }
104
105 bool
106 is_lock_free() const volatile noexcept { return _M_base.is_lock_free(); }
107
108#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
109 static constexpr bool is_always_lock_free = ATOMIC_BOOL_LOCK_FREE == 2;
110#endif
111
112 void
113 store(bool __i, memory_order __m = memory_order_seq_cst) noexcept
114 { _M_base.store(__i, __m); }
115
116 void
117 store(bool __i, memory_order __m = memory_order_seq_cst) volatile noexcept
118 { _M_base.store(__i, __m); }
119
120 bool
121 load(memory_order __m = memory_order_seq_cst) const noexcept
122 { return _M_base.load(__m); }
123
124 bool
125 load(memory_order __m = memory_order_seq_cst) const volatile noexcept
126 { return _M_base.load(__m); }
127
128 bool
129 exchange(bool __i, memory_order __m = memory_order_seq_cst) noexcept
130 { return _M_base.exchange(__i, __m); }
131
132 bool
133 exchange(bool __i,
134 memory_order __m = memory_order_seq_cst) volatile noexcept
135 { return _M_base.exchange(__i, __m); }
136
137 bool
138 compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1,
139 memory_order __m2) noexcept
140 { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); }
141
142 bool
143 compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1,
144 memory_order __m2) volatile noexcept
145 { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); }
146
147 bool
148 compare_exchange_weak(bool& __i1, bool __i2,
149 memory_order __m = memory_order_seq_cst) noexcept
150 { return _M_base.compare_exchange_weak(__i1, __i2, __m); }
151
152 bool
153 compare_exchange_weak(bool& __i1, bool __i2,
154 memory_order __m = memory_order_seq_cst) volatile noexcept
155 { return _M_base.compare_exchange_weak(__i1, __i2, __m); }
156
157 bool
158 compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1,
159 memory_order __m2) noexcept
160 { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); }
161
162 bool
163 compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1,
164 memory_order __m2) volatile noexcept
165 { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); }
166
167 bool
168 compare_exchange_strong(bool& __i1, bool __i2,
169 memory_order __m = memory_order_seq_cst) noexcept
170 { return _M_base.compare_exchange_strong(__i1, __i2, __m); }
171
172 bool
173 compare_exchange_strong(bool& __i1, bool __i2,
174 memory_order __m = memory_order_seq_cst) volatile noexcept
175 { return _M_base.compare_exchange_strong(__i1, __i2, __m); }
176
177#if __cpp_lib_atomic_wait
178 void
179 wait(bool __old, memory_order __m = memory_order_seq_cst) const noexcept
180 { _M_base.wait(__old, __m); }
181
182 // TODO add const volatile overload
183
184 void
185 notify_one() noexcept
186 { _M_base.notify_one(); }
187
188 void
189 notify_all() noexcept
190 { _M_base.notify_all(); }
191#endif // __cpp_lib_atomic_wait
192 };
193
194 /**
195 * @brief Generic atomic type, primary class template.
196 *
197 * @tparam _Tp Type to be made atomic, must be trivially copyable.
198 */
199 template<typename _Tp>
200 struct atomic
201 {
202 using value_type = _Tp;
203
204 private:
205 // Align 1/2/4/8/16-byte types to at least their size.
206 static constexpr int _S_min_alignment
207 = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || sizeof(_Tp) > 16
208 ? 0 : sizeof(_Tp);
209
210 static constexpr int _S_alignment
211 = _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp);
212
213 alignas(_S_alignment) _Tp _M_i;
214
215 static_assert(__is_trivially_copyable(_Tp),
216 "std::atomic requires a trivially copyable type");
217
218 static_assert(sizeof(_Tp) > 0,
219 "Incomplete or zero-sized types are not supported");
220
221 // _GLIBCXX_RESOLVE_LIB_DEFECTS
222 // 4069. std::atomic<volatile T> should be ill-formed
223 static_assert(is_same<_Tp, typename remove_cv<_Tp>::type>::value,
224 "template argument for std::atomic must not be const or volatile");
225
226#if __cplusplus > 201703L
227 static_assert(is_copy_constructible_v<_Tp>);
228 static_assert(is_move_constructible_v<_Tp>);
229 static_assert(is_copy_assignable_v<_Tp>);
230 static_assert(is_move_assignable_v<_Tp>);
231#endif
232
233 public:
234#if __cpp_lib_atomic_value_initialization
235 // _GLIBCXX_RESOLVE_LIB_DEFECTS
236 // 4169. std::atomic<T>'s default constructor should be constrained
237 constexpr atomic() noexcept(is_nothrow_default_constructible_v<_Tp>)
238 requires is_default_constructible_v<_Tp>
239 : _M_i()
240 {}
241#else
242 atomic() = default;
243#endif
244
245 ~atomic() noexcept = default;
246 atomic(const atomic&) = delete;
247 atomic& operator=(const atomic&) = delete;
248 atomic& operator=(const atomic&) volatile = delete;
249
250#pragma GCC diagnostic push
251#pragma GCC diagnostic ignored "-Wc++14-extensions" // constexpr ctor body
252 constexpr atomic(_Tp __i) noexcept : _M_i(__i)
253 {
254#if __has_builtin(__builtin_clear_padding)
255 if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Tp>())
256 if (!std::__is_constant_evaluated())
257 __builtin_clear_padding(std::__addressof(_M_i));
258#endif
259 }
260#pragma GCC diagnostic pop
261
262 operator _Tp() const noexcept
263 { return load(); }
264
265 operator _Tp() const volatile noexcept
266 { return load(); }
267
268 _Tp
269 operator=(_Tp __i) noexcept
270 { store(__i); return __i; }
271
272 _Tp
273 operator=(_Tp __i) volatile noexcept
274 { store(__i); return __i; }
275
276 bool
277 is_lock_free() const noexcept
278 {
279 // Produce a fake, minimally aligned pointer.
280 return __atomic_is_lock_free(sizeof(_M_i),
281 reinterpret_cast<void *>(-_S_alignment));
282 }
283
284 bool
285 is_lock_free() const volatile noexcept
286 {
287 // Produce a fake, minimally aligned pointer.
288 return __atomic_is_lock_free(sizeof(_M_i),
289 reinterpret_cast<void *>(-_S_alignment));
290 }
291
292#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
293 static constexpr bool is_always_lock_free
294 = __atomic_always_lock_free(sizeof(_M_i), 0);
295#endif
296
297 void
298 store(_Tp __i, memory_order __m = memory_order_seq_cst) noexcept
299 {
300 __atomic_store(std::__addressof(_M_i),
301 __atomic_impl::__clear_padding(__i),
302 int(__m));
303 }
304
305 void
306 store(_Tp __i, memory_order __m = memory_order_seq_cst) volatile noexcept
307 {
308 __atomic_store(std::__addressof(_M_i),
309 __atomic_impl::__clear_padding(__i),
310 int(__m));
311 }
312
313 _Tp
314 load(memory_order __m = memory_order_seq_cst) const noexcept
315 {
316 alignas(_Tp) unsigned char __buf[sizeof(_Tp)];
317 _Tp* __ptr = reinterpret_cast<_Tp*>(__buf);
318 __atomic_load(std::__addressof(_M_i), __ptr, int(__m));
319 return *__ptr;
320 }
321
322 _Tp
323 load(memory_order __m = memory_order_seq_cst) const volatile noexcept
324 {
325 alignas(_Tp) unsigned char __buf[sizeof(_Tp)];
326 _Tp* __ptr = reinterpret_cast<_Tp*>(__buf);
327 __atomic_load(std::__addressof(_M_i), __ptr, int(__m));
328 return *__ptr;
329 }
330
331 _Tp
332 exchange(_Tp __i, memory_order __m = memory_order_seq_cst) noexcept
333 {
334 alignas(_Tp) unsigned char __buf[sizeof(_Tp)];
335 _Tp* __ptr = reinterpret_cast<_Tp*>(__buf);
336 __atomic_exchange(std::__addressof(_M_i),
337 __atomic_impl::__clear_padding(__i),
338 __ptr, int(__m));
339 return *__ptr;
340 }
341
342 _Tp
343 exchange(_Tp __i,
344 memory_order __m = memory_order_seq_cst) volatile noexcept
345 {
346 alignas(_Tp) unsigned char __buf[sizeof(_Tp)];
347 _Tp* __ptr = reinterpret_cast<_Tp*>(__buf);
348 __atomic_exchange(std::__addressof(_M_i),
349 __atomic_impl::__clear_padding(__i),
350 __ptr, int(__m));
351 return *__ptr;
352 }
353
354 bool
355 compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s,
356 memory_order __f) noexcept
357 {
358 return __atomic_impl::__compare_exchange(_M_i, __e, __i, true,
359 __s, __f);
360 }
361
362 bool
363 compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s,
364 memory_order __f) volatile noexcept
365 {
366 return __atomic_impl::__compare_exchange(_M_i, __e, __i, true,
367 __s, __f);
368 }
369
370 bool
371 compare_exchange_weak(_Tp& __e, _Tp __i,
372 memory_order __m = memory_order_seq_cst) noexcept
373 { return compare_exchange_weak(__e, __i, __m,
374 __cmpexch_failure_order(__m)); }
375
376 bool
377 compare_exchange_weak(_Tp& __e, _Tp __i,
378 memory_order __m = memory_order_seq_cst) volatile noexcept
379 { return compare_exchange_weak(__e, __i, __m,
380 __cmpexch_failure_order(__m)); }
381
382 bool
383 compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s,
384 memory_order __f) noexcept
385 {
386 return __atomic_impl::__compare_exchange(_M_i, __e, __i, false,
387 __s, __f);
388 }
389
390 bool
391 compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s,
392 memory_order __f) volatile noexcept
393 {
394 return __atomic_impl::__compare_exchange(_M_i, __e, __i, false,
395 __s, __f);
396 }
397
398 bool
399 compare_exchange_strong(_Tp& __e, _Tp __i,
400 memory_order __m = memory_order_seq_cst) noexcept
401 { return compare_exchange_strong(__e, __i, __m,
402 __cmpexch_failure_order(__m)); }
403
404 bool
405 compare_exchange_strong(_Tp& __e, _Tp __i,
406 memory_order __m = memory_order_seq_cst) volatile noexcept
407 { return compare_exchange_strong(__e, __i, __m,
408 __cmpexch_failure_order(__m)); }
409
410#if __cpp_lib_atomic_wait // C++ >= 20
411 void
412 wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept
413 {
414 std::__atomic_wait_address_v(std::addressof(_M_i), __old,
415 [__m, this] { return this->load(__m); });
416 }
417
418 // TODO add const volatile overload
419
420 void
421 notify_one() noexcept
422 { std::__atomic_notify_address(std::addressof(_M_i), false); }
423
424 void
425 notify_all() noexcept
426 { std::__atomic_notify_address(std::addressof(_M_i), true); }
427#endif // __cpp_lib_atomic_wait
428 };
429
430 /// Partial specialization for pointer types.
431 template<typename _Tp>
432 struct atomic<_Tp*>
433 {
434 using value_type = _Tp*;
435 using difference_type = ptrdiff_t;
436
437 typedef _Tp* __pointer_type;
438 typedef __atomic_base<_Tp*> __base_type;
439 __base_type _M_b;
440
441 atomic() noexcept = default;
442 ~atomic() noexcept = default;
443 atomic(const atomic&) = delete;
444 atomic& operator=(const atomic&) = delete;
445 atomic& operator=(const atomic&) volatile = delete;
446
447 constexpr atomic(__pointer_type __p) noexcept : _M_b(__p) { }
448
449 operator __pointer_type() const noexcept
450 { return __pointer_type(_M_b); }
451
452 operator __pointer_type() const volatile noexcept
453 { return __pointer_type(_M_b); }
454
455 __pointer_type
456 operator=(__pointer_type __p) noexcept
457 { return _M_b.operator=(__p); }
458
459 __pointer_type
460 operator=(__pointer_type __p) volatile noexcept
461 { return _M_b.operator=(__p); }
462
463 __pointer_type
464 operator++(int) noexcept
465 {
466#if __cplusplus >= 201703L
467 static_assert( is_object_v<_Tp>, "pointer to object type" );
468#endif
469 return _M_b++;
470 }
471
472 __pointer_type
473 operator++(int) volatile noexcept
474 {
475#if __cplusplus >= 201703L
476 static_assert( is_object_v<_Tp>, "pointer to object type" );
477#endif
478 return _M_b++;
479 }
480
481 __pointer_type
482 operator--(int) noexcept
483 {
484#if __cplusplus >= 201703L
485 static_assert( is_object_v<_Tp>, "pointer to object type" );
486#endif
487 return _M_b--;
488 }
489
490 __pointer_type
491 operator--(int) volatile noexcept
492 {
493#if __cplusplus >= 201703L
494 static_assert( is_object_v<_Tp>, "pointer to object type" );
495#endif
496 return _M_b--;
497 }
498
499 __pointer_type
500 operator++() noexcept
501 {
502#if __cplusplus >= 201703L
503 static_assert( is_object_v<_Tp>, "pointer to object type" );
504#endif
505 return ++_M_b;
506 }
507
508 __pointer_type
509 operator++() volatile noexcept
510 {
511#if __cplusplus >= 201703L
512 static_assert( is_object_v<_Tp>, "pointer to object type" );
513#endif
514 return ++_M_b;
515 }
516
517 __pointer_type
518 operator--() noexcept
519 {
520#if __cplusplus >= 201703L
521 static_assert( is_object_v<_Tp>, "pointer to object type" );
522#endif
523 return --_M_b;
524 }
525
526 __pointer_type
527 operator--() volatile noexcept
528 {
529#if __cplusplus >= 201703L
530 static_assert( is_object_v<_Tp>, "pointer to object type" );
531#endif
532 return --_M_b;
533 }
534
535 __pointer_type
536 operator+=(ptrdiff_t __d) noexcept
537 {
538#if __cplusplus >= 201703L
539 static_assert( is_object_v<_Tp>, "pointer to object type" );
540#endif
541 return _M_b.operator+=(__d);
542 }
543
544 __pointer_type
545 operator+=(ptrdiff_t __d) volatile noexcept
546 {
547#if __cplusplus >= 201703L
548 static_assert( is_object_v<_Tp>, "pointer to object type" );
549#endif
550 return _M_b.operator+=(__d);
551 }
552
553 __pointer_type
554 operator-=(ptrdiff_t __d) noexcept
555 {
556#if __cplusplus >= 201703L
557 static_assert( is_object_v<_Tp>, "pointer to object type" );
558#endif
559 return _M_b.operator-=(__d);
560 }
561
562 __pointer_type
563 operator-=(ptrdiff_t __d) volatile noexcept
564 {
565#if __cplusplus >= 201703L
566 static_assert( is_object_v<_Tp>, "pointer to object type" );
567#endif
568 return _M_b.operator-=(__d);
569 }
570
571 bool
572 is_lock_free() const noexcept
573 { return _M_b.is_lock_free(); }
574
575 bool
576 is_lock_free() const volatile noexcept
577 { return _M_b.is_lock_free(); }
578
579#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
580 static constexpr bool is_always_lock_free
581 = ATOMIC_POINTER_LOCK_FREE == 2;
582#endif
583
584 void
585 store(__pointer_type __p,
586 memory_order __m = memory_order_seq_cst) noexcept
587 { return _M_b.store(__p, __m); }
588
589 void
590 store(__pointer_type __p,
591 memory_order __m = memory_order_seq_cst) volatile noexcept
592 { return _M_b.store(__p, __m); }
593
594 __pointer_type
595 load(memory_order __m = memory_order_seq_cst) const noexcept
596 { return _M_b.load(__m); }
597
598 __pointer_type
599 load(memory_order __m = memory_order_seq_cst) const volatile noexcept
600 { return _M_b.load(__m); }
601
602 __pointer_type
603 exchange(__pointer_type __p,
604 memory_order __m = memory_order_seq_cst) noexcept
605 { return _M_b.exchange(__p, __m); }
606
607 __pointer_type
608 exchange(__pointer_type __p,
609 memory_order __m = memory_order_seq_cst) volatile noexcept
610 { return _M_b.exchange(__p, __m); }
611
612 bool
613 compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2,
614 memory_order __m1, memory_order __m2) noexcept
615 { return _M_b.compare_exchange_weak(__p1, __p2, __m1, __m2); }
616
617 bool
618 compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2,
619 memory_order __m1,
620 memory_order __m2) volatile noexcept
621 { return _M_b.compare_exchange_weak(__p1, __p2, __m1, __m2); }
622
623 bool
624 compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2,
625 memory_order __m = memory_order_seq_cst) noexcept
626 {
627 return compare_exchange_weak(__p1, __p2, __m,
628 __cmpexch_failure_order(__m));
629 }
630
631 bool
632 compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2,
633 memory_order __m = memory_order_seq_cst) volatile noexcept
634 {
635 return compare_exchange_weak(__p1, __p2, __m,
636 __cmpexch_failure_order(__m));
637 }
638
639 bool
640 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
641 memory_order __m1, memory_order __m2) noexcept
642 { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); }
643
644 bool
645 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
646 memory_order __m1,
647 memory_order __m2) volatile noexcept
648 { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); }
649
650 bool
651 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
652 memory_order __m = memory_order_seq_cst) noexcept
653 {
654 return _M_b.compare_exchange_strong(__p1, __p2, __m,
655 __cmpexch_failure_order(__m));
656 }
657
658 bool
659 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
660 memory_order __m = memory_order_seq_cst) volatile noexcept
661 {
662 return _M_b.compare_exchange_strong(__p1, __p2, __m,
663 __cmpexch_failure_order(__m));
664 }
665
666#if __cpp_lib_atomic_wait
667 void
668 wait(__pointer_type __old, memory_order __m = memory_order_seq_cst) const noexcept
669 { _M_b.wait(__old, __m); }
670
671 // TODO add const volatile overload
672
673 void
674 notify_one() noexcept
675 { _M_b.notify_one(); }
676
677 void
678 notify_all() noexcept
679 { _M_b.notify_all(); }
680#endif // __cpp_lib_atomic_wait
681
682 __pointer_type
683 fetch_add(ptrdiff_t __d,
684 memory_order __m = memory_order_seq_cst) noexcept
685 {
686#if __cplusplus >= 201703L
687 static_assert( is_object_v<_Tp>, "pointer to object type" );
688#endif
689 return _M_b.fetch_add(__d, __m);
690 }
691
692 __pointer_type
693 fetch_add(ptrdiff_t __d,
694 memory_order __m = memory_order_seq_cst) volatile noexcept
695 {
696#if __cplusplus >= 201703L
697 static_assert( is_object_v<_Tp>, "pointer to object type" );
698#endif
699 return _M_b.fetch_add(__d, __m);
700 }
701
702 __pointer_type
703 fetch_sub(ptrdiff_t __d,
704 memory_order __m = memory_order_seq_cst) noexcept
705 {
706#if __cplusplus >= 201703L
707 static_assert( is_object_v<_Tp>, "pointer to object type" );
708#endif
709 return _M_b.fetch_sub(__d, __m);
710 }
711
712 __pointer_type
713 fetch_sub(ptrdiff_t __d,
714 memory_order __m = memory_order_seq_cst) volatile noexcept
715 {
716#if __cplusplus >= 201703L
717 static_assert( is_object_v<_Tp>, "pointer to object type" );
718#endif
719 return _M_b.fetch_sub(__d, __m);
720 }
721
722#if __glibcxx_atomic_min_max
723 __pointer_type
724 fetch_min(__pointer_type __p,
725 memory_order __m = memory_order_seq_cst) noexcept
726 { return _M_b.fetch_min(__p, __m); }
727
728 __pointer_type
729 fetch_min(__pointer_type __p,
730 memory_order __m = memory_order_seq_cst) volatile noexcept
731 { return _M_b.fetch_min(__p, __m); }
732
733 __pointer_type
734 fetch_max(__pointer_type __p,
735 memory_order __m = memory_order_seq_cst) noexcept
736 { return _M_b.fetch_max(__p, __m); }
737
738 __pointer_type
739 fetch_max(__pointer_type __p,
740 memory_order __m = memory_order_seq_cst) volatile noexcept
741 { return _M_b.fetch_max(__p, __m); }
742#endif
743 };
744
745
746 /// Explicit specialization for char.
747 template<>
748 struct atomic<char> : __atomic_base<char>
749 {
750 typedef char __integral_type;
751 typedef __atomic_base<char> __base_type;
752
753 atomic() noexcept = default;
754 ~atomic() noexcept = default;
755 atomic(const atomic&) = delete;
756 atomic& operator=(const atomic&) = delete;
757 atomic& operator=(const atomic&) volatile = delete;
758
759 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
760
761 using __base_type::operator __integral_type;
762 using __base_type::operator=;
763
764#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
765 static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2;
766#endif
767 };
768
769 /// Explicit specialization for signed char.
770 template<>
771 struct atomic<signed char> : __atomic_base<signed char>
772 {
773 typedef signed char __integral_type;
774 typedef __atomic_base<signed char> __base_type;
775
776 atomic() noexcept= default;
777 ~atomic() noexcept = default;
778 atomic(const atomic&) = delete;
779 atomic& operator=(const atomic&) = delete;
780 atomic& operator=(const atomic&) volatile = delete;
781
782 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
783
784 using __base_type::operator __integral_type;
785 using __base_type::operator=;
786
787#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
788 static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2;
789#endif
790 };
791
792 /// Explicit specialization for unsigned char.
793 template<>
794 struct atomic<unsigned char> : __atomic_base<unsigned char>
795 {
796 typedef unsigned char __integral_type;
797 typedef __atomic_base<unsigned char> __base_type;
798
799 atomic() noexcept= default;
800 ~atomic() noexcept = default;
801 atomic(const atomic&) = delete;
802 atomic& operator=(const atomic&) = delete;
803 atomic& operator=(const atomic&) volatile = delete;
804
805 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
806
807 using __base_type::operator __integral_type;
808 using __base_type::operator=;
809
810#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
811 static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2;
812#endif
813 };
814
815 /// Explicit specialization for short.
816 template<>
817 struct atomic<short> : __atomic_base<short>
818 {
819 typedef short __integral_type;
820 typedef __atomic_base<short> __base_type;
821
822 atomic() noexcept = default;
823 ~atomic() noexcept = default;
824 atomic(const atomic&) = delete;
825 atomic& operator=(const atomic&) = delete;
826 atomic& operator=(const atomic&) volatile = delete;
827
828 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
829
830 using __base_type::operator __integral_type;
831 using __base_type::operator=;
832
833#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
834 static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2;
835#endif
836 };
837
838 /// Explicit specialization for unsigned short.
839 template<>
840 struct atomic<unsigned short> : __atomic_base<unsigned short>
841 {
842 typedef unsigned short __integral_type;
843 typedef __atomic_base<unsigned short> __base_type;
844
845 atomic() noexcept = default;
846 ~atomic() noexcept = default;
847 atomic(const atomic&) = delete;
848 atomic& operator=(const atomic&) = delete;
849 atomic& operator=(const atomic&) volatile = delete;
850
851 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
852
853 using __base_type::operator __integral_type;
854 using __base_type::operator=;
855
856#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
857 static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2;
858#endif
859 };
860
861 /// Explicit specialization for int.
862 template<>
863 struct atomic<int> : __atomic_base<int>
864 {
865 typedef int __integral_type;
866 typedef __atomic_base<int> __base_type;
867
868 atomic() noexcept = default;
869 ~atomic() noexcept = default;
870 atomic(const atomic&) = delete;
871 atomic& operator=(const atomic&) = delete;
872 atomic& operator=(const atomic&) volatile = delete;
873
874 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
875
876 using __base_type::operator __integral_type;
877 using __base_type::operator=;
878
879#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
880 static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2;
881#endif
882 };
883
884 /// Explicit specialization for unsigned int.
885 template<>
886 struct atomic<unsigned int> : __atomic_base<unsigned int>
887 {
888 typedef unsigned int __integral_type;
889 typedef __atomic_base<unsigned int> __base_type;
890
891 atomic() noexcept = default;
892 ~atomic() noexcept = default;
893 atomic(const atomic&) = delete;
894 atomic& operator=(const atomic&) = delete;
895 atomic& operator=(const atomic&) volatile = delete;
896
897 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
898
899 using __base_type::operator __integral_type;
900 using __base_type::operator=;
901
902#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
903 static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2;
904#endif
905 };
906
907 /// Explicit specialization for long.
908 template<>
909 struct atomic<long> : __atomic_base<long>
910 {
911 typedef long __integral_type;
912 typedef __atomic_base<long> __base_type;
913
914 atomic() noexcept = default;
915 ~atomic() noexcept = default;
916 atomic(const atomic&) = delete;
917 atomic& operator=(const atomic&) = delete;
918 atomic& operator=(const atomic&) volatile = delete;
919
920 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
921
922 using __base_type::operator __integral_type;
923 using __base_type::operator=;
924
925#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
926 static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2;
927#endif
928 };
929
930 /// Explicit specialization for unsigned long.
931 template<>
932 struct atomic<unsigned long> : __atomic_base<unsigned long>
933 {
934 typedef unsigned long __integral_type;
935 typedef __atomic_base<unsigned long> __base_type;
936
937 atomic() noexcept = default;
938 ~atomic() noexcept = default;
939 atomic(const atomic&) = delete;
940 atomic& operator=(const atomic&) = delete;
941 atomic& operator=(const atomic&) volatile = delete;
942
943 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
944
945 using __base_type::operator __integral_type;
946 using __base_type::operator=;
947
948#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
949 static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2;
950#endif
951 };
952
953 /// Explicit specialization for long long.
954 template<>
955 struct atomic<long long> : __atomic_base<long long>
956 {
957 typedef long long __integral_type;
958 typedef __atomic_base<long long> __base_type;
959
960 atomic() noexcept = default;
961 ~atomic() noexcept = default;
962 atomic(const atomic&) = delete;
963 atomic& operator=(const atomic&) = delete;
964 atomic& operator=(const atomic&) volatile = delete;
965
966 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
967
968 using __base_type::operator __integral_type;
969 using __base_type::operator=;
970
971#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
972 static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2;
973#endif
974 };
975
976 /// Explicit specialization for unsigned long long.
977 template<>
978 struct atomic<unsigned long long> : __atomic_base<unsigned long long>
979 {
980 typedef unsigned long long __integral_type;
981 typedef __atomic_base<unsigned long long> __base_type;
982
983 atomic() noexcept = default;
984 ~atomic() noexcept = default;
985 atomic(const atomic&) = delete;
986 atomic& operator=(const atomic&) = delete;
987 atomic& operator=(const atomic&) volatile = delete;
988
989 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
990
991 using __base_type::operator __integral_type;
992 using __base_type::operator=;
993
994#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
995 static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2;
996#endif
997 };
998
999 /// Explicit specialization for wchar_t.
1000 template<>
1001 struct atomic<wchar_t> : __atomic_base<wchar_t>
1002 {
1003 typedef wchar_t __integral_type;
1004 typedef __atomic_base<wchar_t> __base_type;
1005
1006 atomic() noexcept = default;
1007 ~atomic() noexcept = default;
1008 atomic(const atomic&) = delete;
1009 atomic& operator=(const atomic&) = delete;
1010 atomic& operator=(const atomic&) volatile = delete;
1011
1012 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
1013
1014 using __base_type::operator __integral_type;
1015 using __base_type::operator=;
1016
1017#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
1018 static constexpr bool is_always_lock_free = ATOMIC_WCHAR_T_LOCK_FREE == 2;
1019#endif
1020 };
1021
1022#ifdef _GLIBCXX_USE_CHAR8_T
1023 /// Explicit specialization for char8_t.
1024 template<>
1025 struct atomic<char8_t> : __atomic_base<char8_t>
1026 {
1027 typedef char8_t __integral_type;
1028 typedef __atomic_base<char8_t> __base_type;
1029
1030 atomic() noexcept = default;
1031 ~atomic() noexcept = default;
1032 atomic(const atomic&) = delete;
1033 atomic& operator=(const atomic&) = delete;
1034 atomic& operator=(const atomic&) volatile = delete;
1035
1036 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
1037
1038 using __base_type::operator __integral_type;
1039 using __base_type::operator=;
1040
1041#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
1042 static constexpr bool is_always_lock_free
1043 = ATOMIC_CHAR8_T_LOCK_FREE == 2;
1044#endif
1045 };
1046#endif
1047
1048 /// Explicit specialization for char16_t.
1049 template<>
1050 struct atomic<char16_t> : __atomic_base<char16_t>
1051 {
1052 typedef char16_t __integral_type;
1053 typedef __atomic_base<char16_t> __base_type;
1054
1055 atomic() noexcept = default;
1056 ~atomic() noexcept = default;
1057 atomic(const atomic&) = delete;
1058 atomic& operator=(const atomic&) = delete;
1059 atomic& operator=(const atomic&) volatile = delete;
1060
1061 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
1062
1063 using __base_type::operator __integral_type;
1064 using __base_type::operator=;
1065
1066#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
1067 static constexpr bool is_always_lock_free
1068 = ATOMIC_CHAR16_T_LOCK_FREE == 2;
1069#endif
1070 };
1071
1072 /// Explicit specialization for char32_t.
1073 template<>
1074 struct atomic<char32_t> : __atomic_base<char32_t>
1075 {
1076 typedef char32_t __integral_type;
1077 typedef __atomic_base<char32_t> __base_type;
1078
1079 atomic() noexcept = default;
1080 ~atomic() noexcept = default;
1081 atomic(const atomic&) = delete;
1082 atomic& operator=(const atomic&) = delete;
1083 atomic& operator=(const atomic&) volatile = delete;
1084
1085 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
1086
1087 using __base_type::operator __integral_type;
1088 using __base_type::operator=;
1089
1090#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
1091 static constexpr bool is_always_lock_free
1092 = ATOMIC_CHAR32_T_LOCK_FREE == 2;
1093#endif
1094 };
1095
1096
1097 /// atomic_bool
1099
1100 /// atomic_char
1102
1103 /// atomic_schar
1105
1106 /// atomic_uchar
1108
1109 /// atomic_short
1111
1112 /// atomic_ushort
1114
1115 /// atomic_int
1117
1118 /// atomic_uint
1120
1121 /// atomic_long
1123
1124 /// atomic_ulong
1126
1127 /// atomic_llong
1129
1130 /// atomic_ullong
1132
1133 /// atomic_wchar_t
1135
1136#ifdef _GLIBCXX_USE_CHAR8_T
1137 /// atomic_char8_t
1138 typedef atomic<char8_t> atomic_char8_t;
1139#endif
1140
1141 /// atomic_char16_t
1143
1144 /// atomic_char32_t
1146
1147#ifdef _GLIBCXX_USE_C99_STDINT
1148 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1149 // 2441. Exact-width atomic typedefs should be provided
1150
1151 /// atomic_int8_t
1153
1154 /// atomic_uint8_t
1156
1157 /// atomic_int16_t
1159
1160 /// atomic_uint16_t
1162
1163 /// atomic_int32_t
1165
1166 /// atomic_uint32_t
1168
1169 /// atomic_int64_t
1171
1172 /// atomic_uint64_t
1174#endif
1175
1176 /// atomic_int_least8_t
1178
1179 /// atomic_uint_least8_t
1181
1182 /// atomic_int_least16_t
1184
1185 /// atomic_uint_least16_t
1187
1188 /// atomic_int_least32_t
1190
1191 /// atomic_uint_least32_t
1193
1194 /// atomic_int_least64_t
1196
1197 /// atomic_uint_least64_t
1199
1200
1201 /// atomic_int_fast8_t
1203
1204 /// atomic_uint_fast8_t
1206
1207 /// atomic_int_fast16_t
1209
1210 /// atomic_uint_fast16_t
1212
1213 /// atomic_int_fast32_t
1215
1216 /// atomic_uint_fast32_t
1218
1219 /// atomic_int_fast64_t
1221
1222 /// atomic_uint_fast64_t
1224
1225
1226 /// atomic_intptr_t
1228
1229 /// atomic_uintptr_t
1231
1232 /// atomic_size_t
1234
1235 /// atomic_ptrdiff_t
1237
1238 /// atomic_intmax_t
1240
1241 /// atomic_uintmax_t
1243
1244 // Function definitions, atomic_flag operations.
1245 inline bool
1246 atomic_flag_test_and_set_explicit(atomic_flag* __a,
1247 memory_order __m) noexcept
1248 { return __a->test_and_set(__m); }
1249
1250 inline bool
1251 atomic_flag_test_and_set_explicit(volatile atomic_flag* __a,
1252 memory_order __m) noexcept
1253 { return __a->test_and_set(__m); }
1254
1255#if __cpp_lib_atomic_flag_test
1256 inline bool
1257 atomic_flag_test(const atomic_flag* __a) noexcept
1258 { return __a->test(); }
1259
1260 inline bool
1261 atomic_flag_test(const volatile atomic_flag* __a) noexcept
1262 { return __a->test(); }
1263
1264 inline bool
1265 atomic_flag_test_explicit(const atomic_flag* __a,
1266 memory_order __m) noexcept
1267 { return __a->test(__m); }
1268
1269 inline bool
1270 atomic_flag_test_explicit(const volatile atomic_flag* __a,
1271 memory_order __m) noexcept
1272 { return __a->test(__m); }
1273#endif
1274
1275 inline void
1276 atomic_flag_clear_explicit(atomic_flag* __a, memory_order __m) noexcept
1277 { __a->clear(__m); }
1278
1279 inline void
1280 atomic_flag_clear_explicit(volatile atomic_flag* __a,
1281 memory_order __m) noexcept
1282 { __a->clear(__m); }
1283
1284 inline bool
1285 atomic_flag_test_and_set(atomic_flag* __a) noexcept
1286 { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); }
1287
1288 inline bool
1289 atomic_flag_test_and_set(volatile atomic_flag* __a) noexcept
1290 { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); }
1291
1292 inline void
1293 atomic_flag_clear(atomic_flag* __a) noexcept
1294 { atomic_flag_clear_explicit(__a, memory_order_seq_cst); }
1295
1296 inline void
1297 atomic_flag_clear(volatile atomic_flag* __a) noexcept
1298 { atomic_flag_clear_explicit(__a, memory_order_seq_cst); }
1299
1300#if __cpp_lib_atomic_wait
1301 inline void
1302 atomic_flag_wait(atomic_flag* __a, bool __old) noexcept
1303 { __a->wait(__old); }
1304
1305 inline void
1306 atomic_flag_wait_explicit(atomic_flag* __a, bool __old,
1307 memory_order __m) noexcept
1308 { __a->wait(__old, __m); }
1309
1310 inline void
1311 atomic_flag_notify_one(atomic_flag* __a) noexcept
1312 { __a->notify_one(); }
1313
1314 inline void
1315 atomic_flag_notify_all(atomic_flag* __a) noexcept
1316 { __a->notify_all(); }
1317#endif // __cpp_lib_atomic_wait
1318
1319 /// @cond undocumented
1320 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1321 // 3220. P0558 broke conforming C++14 uses of atomic shared_ptr
1322 template<typename _Tp>
1323 using __atomic_val_t = __type_identity_t<_Tp>;
1324 template<typename _Tp>
1325 using __atomic_diff_t = typename atomic<_Tp>::difference_type;
1326 /// @endcond
1327
1328 // [atomics.nonmembers] Non-member functions.
1329 // Function templates generally applicable to atomic types.
1330 template<typename _ITp>
1331 inline bool
1332 atomic_is_lock_free(const atomic<_ITp>* __a) noexcept
1333 { return __a->is_lock_free(); }
1334
1335 template<typename _ITp>
1336 inline bool
1337 atomic_is_lock_free(const volatile atomic<_ITp>* __a) noexcept
1338 { return __a->is_lock_free(); }
1339
1340 template<typename _ITp>
1341 inline void
1342 atomic_init(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept
1343 { __a->store(__i, memory_order_relaxed); }
1344
1345 template<typename _ITp>
1346 inline void
1347 atomic_init(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept
1348 { __a->store(__i, memory_order_relaxed); }
1349
1350 template<typename _ITp>
1351 inline void
1352 atomic_store_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i,
1353 memory_order __m) noexcept
1354 { __a->store(__i, __m); }
1355
1356 template<typename _ITp>
1357 inline void
1358 atomic_store_explicit(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i,
1359 memory_order __m) noexcept
1360 { __a->store(__i, __m); }
1361
1362 template<typename _ITp>
1363 inline _ITp
1364 atomic_load_explicit(const atomic<_ITp>* __a, memory_order __m) noexcept
1365 { return __a->load(__m); }
1366
1367 template<typename _ITp>
1368 inline _ITp
1369 atomic_load_explicit(const volatile atomic<_ITp>* __a,
1370 memory_order __m) noexcept
1371 { return __a->load(__m); }
1372
1373 template<typename _ITp>
1374 inline _ITp
1375 atomic_exchange_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i,
1376 memory_order __m) noexcept
1377 { return __a->exchange(__i, __m); }
1378
1379 template<typename _ITp>
1380 inline _ITp
1381 atomic_exchange_explicit(volatile atomic<_ITp>* __a,
1382 __atomic_val_t<_ITp> __i,
1383 memory_order __m) noexcept
1384 { return __a->exchange(__i, __m); }
1385
1386 template<typename _ITp>
1387 inline bool
1388 atomic_compare_exchange_weak_explicit(atomic<_ITp>* __a,
1389 __atomic_val_t<_ITp>* __i1,
1390 __atomic_val_t<_ITp> __i2,
1391 memory_order __m1,
1392 memory_order __m2) noexcept
1393 { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); }
1394
1395 template<typename _ITp>
1396 inline bool
1397 atomic_compare_exchange_weak_explicit(volatile atomic<_ITp>* __a,
1398 __atomic_val_t<_ITp>* __i1,
1399 __atomic_val_t<_ITp> __i2,
1400 memory_order __m1,
1401 memory_order __m2) noexcept
1402 { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); }
1403
1404 template<typename _ITp>
1405 inline bool
1406 atomic_compare_exchange_strong_explicit(atomic<_ITp>* __a,
1407 __atomic_val_t<_ITp>* __i1,
1408 __atomic_val_t<_ITp> __i2,
1409 memory_order __m1,
1410 memory_order __m2) noexcept
1411 { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); }
1412
1413 template<typename _ITp>
1414 inline bool
1415 atomic_compare_exchange_strong_explicit(volatile atomic<_ITp>* __a,
1416 __atomic_val_t<_ITp>* __i1,
1417 __atomic_val_t<_ITp> __i2,
1418 memory_order __m1,
1419 memory_order __m2) noexcept
1420 { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); }
1421
1422
1423 template<typename _ITp>
1424 inline void
1425 atomic_store(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept
1426 { atomic_store_explicit(__a, __i, memory_order_seq_cst); }
1427
1428 template<typename _ITp>
1429 inline void
1430 atomic_store(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept
1431 { atomic_store_explicit(__a, __i, memory_order_seq_cst); }
1432
1433 template<typename _ITp>
1434 inline _ITp
1435 atomic_load(const atomic<_ITp>* __a) noexcept
1436 { return atomic_load_explicit(__a, memory_order_seq_cst); }
1437
1438 template<typename _ITp>
1439 inline _ITp
1440 atomic_load(const volatile atomic<_ITp>* __a) noexcept
1441 { return atomic_load_explicit(__a, memory_order_seq_cst); }
1442
1443 template<typename _ITp>
1444 inline _ITp
1445 atomic_exchange(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept
1446 { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); }
1447
1448 template<typename _ITp>
1449 inline _ITp
1450 atomic_exchange(volatile atomic<_ITp>* __a,
1451 __atomic_val_t<_ITp> __i) noexcept
1452 { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); }
1453
1454 template<typename _ITp>
1455 inline bool
1456 atomic_compare_exchange_weak(atomic<_ITp>* __a,
1457 __atomic_val_t<_ITp>* __i1,
1458 __atomic_val_t<_ITp> __i2) noexcept
1459 {
1460 return atomic_compare_exchange_weak_explicit(__a, __i1, __i2,
1461 memory_order_seq_cst,
1462 memory_order_seq_cst);
1463 }
1464
1465 template<typename _ITp>
1466 inline bool
1467 atomic_compare_exchange_weak(volatile atomic<_ITp>* __a,
1468 __atomic_val_t<_ITp>* __i1,
1469 __atomic_val_t<_ITp> __i2) noexcept
1470 {
1471 return atomic_compare_exchange_weak_explicit(__a, __i1, __i2,
1472 memory_order_seq_cst,
1473 memory_order_seq_cst);
1474 }
1475
1476 template<typename _ITp>
1477 inline bool
1478 atomic_compare_exchange_strong(atomic<_ITp>* __a,
1479 __atomic_val_t<_ITp>* __i1,
1480 __atomic_val_t<_ITp> __i2) noexcept
1481 {
1482 return atomic_compare_exchange_strong_explicit(__a, __i1, __i2,
1483 memory_order_seq_cst,
1484 memory_order_seq_cst);
1485 }
1486
1487 template<typename _ITp>
1488 inline bool
1489 atomic_compare_exchange_strong(volatile atomic<_ITp>* __a,
1490 __atomic_val_t<_ITp>* __i1,
1491 __atomic_val_t<_ITp> __i2) noexcept
1492 {
1493 return atomic_compare_exchange_strong_explicit(__a, __i1, __i2,
1494 memory_order_seq_cst,
1495 memory_order_seq_cst);
1496 }
1497
1498
1499#if __cpp_lib_atomic_wait
1500 template<typename _Tp>
1501 inline void
1502 atomic_wait(const atomic<_Tp>* __a,
1503 typename std::atomic<_Tp>::value_type __old) noexcept
1504 { __a->wait(__old); }
1505
1506 template<typename _Tp>
1507 inline void
1508 atomic_wait_explicit(const atomic<_Tp>* __a,
1509 typename std::atomic<_Tp>::value_type __old,
1510 std::memory_order __m) noexcept
1511 { __a->wait(__old, __m); }
1512
1513 template<typename _Tp>
1514 inline void
1515 atomic_notify_one(atomic<_Tp>* __a) noexcept
1516 { __a->notify_one(); }
1517
1518 template<typename _Tp>
1519 inline void
1520 atomic_notify_all(atomic<_Tp>* __a) noexcept
1521 { __a->notify_all(); }
1522#endif // __cpp_lib_atomic_wait
1523
1524 // Function templates for atomic_integral and atomic_pointer operations only.
1525 // Some operations (and, or, xor) are only available for atomic integrals,
1526 // which is implemented by taking a parameter of type __atomic_base<_ITp>*.
1527
1528 template<typename _ITp>
1529 inline _ITp
1530 atomic_fetch_add_explicit(atomic<_ITp>* __a,
1531 __atomic_diff_t<_ITp> __i,
1532 memory_order __m) noexcept
1533 { return __a->fetch_add(__i, __m); }
1534
1535 template<typename _ITp>
1536 inline _ITp
1537 atomic_fetch_add_explicit(volatile atomic<_ITp>* __a,
1538 __atomic_diff_t<_ITp> __i,
1539 memory_order __m) noexcept
1540 { return __a->fetch_add(__i, __m); }
1541
1542 template<typename _ITp>
1543 inline _ITp
1544 atomic_fetch_sub_explicit(atomic<_ITp>* __a,
1545 __atomic_diff_t<_ITp> __i,
1546 memory_order __m) noexcept
1547 { return __a->fetch_sub(__i, __m); }
1548
1549 template<typename _ITp>
1550 inline _ITp
1551 atomic_fetch_sub_explicit(volatile atomic<_ITp>* __a,
1552 __atomic_diff_t<_ITp> __i,
1553 memory_order __m) noexcept
1554 { return __a->fetch_sub(__i, __m); }
1555
1556 template<typename _ITp>
1557 inline _ITp
1558 atomic_fetch_and_explicit(__atomic_base<_ITp>* __a,
1559 __atomic_val_t<_ITp> __i,
1560 memory_order __m) noexcept
1561 { return __a->fetch_and(__i, __m); }
1562
1563 template<typename _ITp>
1564 inline _ITp
1565 atomic_fetch_and_explicit(volatile __atomic_base<_ITp>* __a,
1566 __atomic_val_t<_ITp> __i,
1567 memory_order __m) noexcept
1568 { return __a->fetch_and(__i, __m); }
1569
1570 template<typename _ITp>
1571 inline _ITp
1572 atomic_fetch_or_explicit(__atomic_base<_ITp>* __a,
1573 __atomic_val_t<_ITp> __i,
1574 memory_order __m) noexcept
1575 { return __a->fetch_or(__i, __m); }
1576
1577 template<typename _ITp>
1578 inline _ITp
1579 atomic_fetch_or_explicit(volatile __atomic_base<_ITp>* __a,
1580 __atomic_val_t<_ITp> __i,
1581 memory_order __m) noexcept
1582 { return __a->fetch_or(__i, __m); }
1583
1584 template<typename _ITp>
1585 inline _ITp
1586 atomic_fetch_xor_explicit(__atomic_base<_ITp>* __a,
1587 __atomic_val_t<_ITp> __i,
1588 memory_order __m) noexcept
1589 { return __a->fetch_xor(__i, __m); }
1590
1591 template<typename _ITp>
1592 inline _ITp
1593 atomic_fetch_xor_explicit(volatile __atomic_base<_ITp>* __a,
1594 __atomic_val_t<_ITp> __i,
1595 memory_order __m) noexcept
1596 { return __a->fetch_xor(__i, __m); }
1597
1598#ifdef __cpp_lib_atomic_min_max
1599 template<typename _Tp>
1600 inline _Tp
1601 atomic_fetch_min_explicit(atomic<_Tp>* __a,
1602 __atomic_val_t<_Tp> __i,
1603 memory_order __m) noexcept
1604 { return __a->fetch_min(__i, __m); }
1605
1606 template<typename _Tp>
1607 inline _Tp
1608 atomic_fetch_min_explicit(volatile atomic<_Tp>* __a,
1609 __atomic_val_t<_Tp> __i,
1610 memory_order __m) noexcept
1611 { return __a->fetch_min(__i, __m); }
1612
1613 template<typename _Tp>
1614 inline _Tp
1615 atomic_fetch_max_explicit(atomic<_Tp>* __a,
1616 __atomic_val_t<_Tp> __i,
1617 memory_order __m) noexcept
1618 { return __a->fetch_max(__i, __m); }
1619
1620 template<typename _Tp>
1621 inline _Tp
1622 atomic_fetch_max_explicit(volatile atomic<_Tp>* __a,
1623 __atomic_val_t<_Tp> __i,
1624 memory_order __m) noexcept
1625 { return __a->fetch_max(__i, __m); }
1626#endif
1627
1628 template<typename _ITp>
1629 inline _ITp
1630 atomic_fetch_add(atomic<_ITp>* __a,
1631 __atomic_diff_t<_ITp> __i) noexcept
1632 { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); }
1633
1634 template<typename _ITp>
1635 inline _ITp
1636 atomic_fetch_add(volatile atomic<_ITp>* __a,
1637 __atomic_diff_t<_ITp> __i) noexcept
1638 { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); }
1639
1640 template<typename _ITp>
1641 inline _ITp
1642 atomic_fetch_sub(atomic<_ITp>* __a,
1643 __atomic_diff_t<_ITp> __i) noexcept
1644 { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); }
1645
1646 template<typename _ITp>
1647 inline _ITp
1648 atomic_fetch_sub(volatile atomic<_ITp>* __a,
1649 __atomic_diff_t<_ITp> __i) noexcept
1650 { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); }
1651
1652 template<typename _ITp>
1653 inline _ITp
1654 atomic_fetch_and(__atomic_base<_ITp>* __a,
1655 __atomic_val_t<_ITp> __i) noexcept
1656 { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); }
1657
1658 template<typename _ITp>
1659 inline _ITp
1660 atomic_fetch_and(volatile __atomic_base<_ITp>* __a,
1661 __atomic_val_t<_ITp> __i) noexcept
1662 { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); }
1663
1664 template<typename _ITp>
1665 inline _ITp
1666 atomic_fetch_or(__atomic_base<_ITp>* __a,
1667 __atomic_val_t<_ITp> __i) noexcept
1668 { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); }
1669
1670 template<typename _ITp>
1671 inline _ITp
1672 atomic_fetch_or(volatile __atomic_base<_ITp>* __a,
1673 __atomic_val_t<_ITp> __i) noexcept
1674 { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); }
1675
1676 template<typename _ITp>
1677 inline _ITp
1678 atomic_fetch_xor(__atomic_base<_ITp>* __a,
1679 __atomic_val_t<_ITp> __i) noexcept
1680 { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); }
1681
1682 template<typename _ITp>
1683 inline _ITp
1684 atomic_fetch_xor(volatile __atomic_base<_ITp>* __a,
1685 __atomic_val_t<_ITp> __i) noexcept
1686 { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); }
1687
1688#ifdef __cpp_lib_atomic_min_max
1689 template<typename _Tp>
1690 inline _Tp
1691 atomic_fetch_min(atomic<_Tp>* __a,
1692 __atomic_val_t<_Tp> __i) noexcept
1693 { return atomic_fetch_min_explicit(__a, __i, memory_order_seq_cst); }
1694
1695 template<typename _Tp>
1696 inline _Tp
1697 atomic_fetch_min(volatile atomic<_Tp>* __a,
1698 __atomic_val_t<_Tp> __i) noexcept
1699 { return atomic_fetch_min_explicit(__a, __i, memory_order_seq_cst); }
1700
1701 template<typename _Tp>
1702 inline _Tp
1703 atomic_fetch_max(atomic<_Tp>* __a,
1704 __atomic_val_t<_Tp> __i) noexcept
1705 { return atomic_fetch_max_explicit(__a, __i, memory_order_seq_cst); }
1706
1707 template<typename _Tp>
1708 inline _Tp
1709 atomic_fetch_max(volatile atomic<_Tp>* __a,
1710 __atomic_val_t<_Tp> __i) noexcept
1711 { return atomic_fetch_max_explicit(__a, __i, memory_order_seq_cst); }
1712#endif
1713
1714#ifdef __cpp_lib_atomic_float
1715 template<>
1716 struct atomic<float> : __atomic_float<float>
1717 {
1718 atomic() noexcept = default;
1719
1720 constexpr
1721 atomic(float __fp) noexcept : __atomic_float<float>(__fp)
1722 { }
1723
1724 atomic& operator=(const atomic&) volatile = delete;
1725 atomic& operator=(const atomic&) = delete;
1726
1727 using __atomic_float<float>::operator=;
1728 };
1729
1730 template<>
1731 struct atomic<double> : __atomic_float<double>
1732 {
1733 atomic() noexcept = default;
1734
1735 constexpr
1736 atomic(double __fp) noexcept : __atomic_float<double>(__fp)
1737 { }
1738
1739 atomic& operator=(const atomic&) volatile = delete;
1740 atomic& operator=(const atomic&) = delete;
1741
1742 using __atomic_float<double>::operator=;
1743 };
1744
1745 template<>
1746 struct atomic<long double> : __atomic_float<long double>
1747 {
1748 atomic() noexcept = default;
1749
1750 constexpr
1751 atomic(long double __fp) noexcept : __atomic_float<long double>(__fp)
1752 { }
1753
1754 atomic& operator=(const atomic&) volatile = delete;
1755 atomic& operator=(const atomic&) = delete;
1756
1757 using __atomic_float<long double>::operator=;
1758 };
1759
1760#ifdef __STDCPP_FLOAT16_T__
1761 template<>
1762 struct atomic<_Float16> : __atomic_float<_Float16>
1763 {
1764 atomic() noexcept = default;
1765
1766 constexpr
1767 atomic(_Float16 __fp) noexcept : __atomic_float<_Float16>(__fp)
1768 { }
1769
1770 atomic& operator=(const atomic&) volatile = delete;
1771 atomic& operator=(const atomic&) = delete;
1772
1773 using __atomic_float<_Float16>::operator=;
1774 };
1775#endif
1776
1777#ifdef __STDCPP_FLOAT32_T__
1778 template<>
1779 struct atomic<_Float32> : __atomic_float<_Float32>
1780 {
1781 atomic() noexcept = default;
1782
1783 constexpr
1784 atomic(_Float32 __fp) noexcept : __atomic_float<_Float32>(__fp)
1785 { }
1786
1787 atomic& operator=(const atomic&) volatile = delete;
1788 atomic& operator=(const atomic&) = delete;
1789
1790 using __atomic_float<_Float32>::operator=;
1791 };
1792#endif
1793
1794#ifdef __STDCPP_FLOAT64_T__
1795 template<>
1796 struct atomic<_Float64> : __atomic_float<_Float64>
1797 {
1798 atomic() noexcept = default;
1799
1800 constexpr
1801 atomic(_Float64 __fp) noexcept : __atomic_float<_Float64>(__fp)
1802 { }
1803
1804 atomic& operator=(const atomic&) volatile = delete;
1805 atomic& operator=(const atomic&) = delete;
1806
1807 using __atomic_float<_Float64>::operator=;
1808 };
1809#endif
1810
1811#ifdef __STDCPP_FLOAT128_T__
1812 template<>
1813 struct atomic<_Float128> : __atomic_float<_Float128>
1814 {
1815 atomic() noexcept = default;
1816
1817 constexpr
1818 atomic(_Float128 __fp) noexcept : __atomic_float<_Float128>(__fp)
1819 { }
1820
1821 atomic& operator=(const atomic&) volatile = delete;
1822 atomic& operator=(const atomic&) = delete;
1823
1824 using __atomic_float<_Float128>::operator=;
1825 };
1826#endif
1827
1828#ifdef __STDCPP_BFLOAT16_T__
1829 template<>
1830 struct atomic<__gnu_cxx::__bfloat16_t> : __atomic_float<__gnu_cxx::__bfloat16_t>
1831 {
1832 atomic() noexcept = default;
1833
1834 constexpr
1835 atomic(__gnu_cxx::__bfloat16_t __fp) noexcept : __atomic_float<__gnu_cxx::__bfloat16_t>(__fp)
1836 { }
1837
1838 atomic& operator=(const atomic&) volatile = delete;
1839 atomic& operator=(const atomic&) = delete;
1840
1841 using __atomic_float<__gnu_cxx::__bfloat16_t>::operator=;
1842 };
1843#endif
1844#endif // __cpp_lib_atomic_float
1845
1846#ifdef __cpp_lib_atomic_ref
1847 /// Class template to provide atomic operations on a non-atomic variable.
1848 template<typename _Tp>
1849 struct atomic_ref : __atomic_ref<_Tp>
1850 {
1851 explicit
1852 atomic_ref(_Tp& __t) noexcept
1853 : __atomic_ref<_Tp>(std::addressof(__t))
1854 {
1855 __glibcxx_assert(((__UINTPTR_TYPE__)this->_M_ptr % this->required_alignment) == 0);
1856 }
1857
1858 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1859 // 4472. std::atomic_ref<const T> can be constructed from temporaries
1860 explicit
1861 atomic_ref(_Tp&&) = delete;
1862
1863 template<typename _Up>
1864 requires is_convertible_v<_Up(*)[1], _Tp(*)[1]>
1865 atomic_ref(atomic_ref<_Up> __other) noexcept
1866 : __atomic_ref<_Tp>(__other._M_ptr)
1867 { }
1868
1869 atomic_ref& operator=(const atomic_ref&) = delete;
1870
1871 atomic_ref(const atomic_ref&) = default;
1872
1873 using __atomic_ref<_Tp>::operator=;
1874
1875 template<typename>
1876 friend struct atomic_ref;
1877 };
1878#endif // __cpp_lib_atomic_ref
1879
1880#ifdef __cpp_lib_atomic_lock_free_type_aliases
1881# ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
1882 using atomic_signed_lock_free
1884 using atomic_unsigned_lock_free
1886# elif ATOMIC_INT_LOCK_FREE == 2
1887 using atomic_signed_lock_free = atomic<signed int>;
1888 using atomic_unsigned_lock_free = atomic<unsigned int>;
1889# elif ATOMIC_LONG_LOCK_FREE == 2
1890 using atomic_signed_lock_free = atomic<signed long>;
1891 using atomic_unsigned_lock_free = atomic<unsigned long>;
1892# elif ATOMIC_CHAR_LOCK_FREE == 2
1893 using atomic_signed_lock_free = atomic<signed char>;
1894 using atomic_unsigned_lock_free = atomic<unsigned char>;
1895# else
1896# error "libstdc++ bug: no lock-free atomics but they were emitted in <version>"
1897# endif
1898#endif
1899
1900 /// @} group atomics
1901
1902_GLIBCXX_END_NAMESPACE_VERSION
1903} // namespace
1904
1905#endif // C++11
1906
1907#endif // _GLIBCXX_ATOMIC
constexpr _Tp * addressof(_Tp &__r) noexcept
Returns the actual address of the object or function referenced by r, even in the presence of an over...
Definition move.h:176
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition move.h:52
atomic< unsigned long > atomic_ulong
atomic_ulong
Definition atomic:1125
atomic< intmax_t > atomic_intmax_t
atomic_intmax_t
Definition atomic:1239
atomic< uintptr_t > atomic_uintptr_t
atomic_uintptr_t
Definition atomic:1230
atomic< signed char > atomic_schar
atomic_schar
Definition atomic:1104
atomic< int_least8_t > atomic_int_least8_t
atomic_int_least8_t
Definition atomic:1177
atomic< unsigned long long > atomic_ullong
atomic_ullong
Definition atomic:1131
atomic< uint_fast8_t > atomic_uint_fast8_t
atomic_uint_fast8_t
Definition atomic:1205
atomic< intptr_t > atomic_intptr_t
atomic_intptr_t
Definition atomic:1227
atomic< int16_t > atomic_int16_t
atomic_int16_t
Definition atomic:1158
atomic< size_t > atomic_size_t
atomic_size_t
Definition atomic:1233
atomic< long > atomic_long
atomic_long
Definition atomic:1122
atomic< uint_least8_t > atomic_uint_least8_t
atomic_uint_least8_t
Definition atomic:1180
atomic< short > atomic_short
atomic_short
Definition atomic:1110
atomic< uint_least16_t > atomic_uint_least16_t
atomic_uint_least16_t
Definition atomic:1186
atomic< uint16_t > atomic_uint16_t
atomic_uint16_t
Definition atomic:1161
atomic< uint64_t > atomic_uint64_t
atomic_uint64_t
Definition atomic:1173
atomic< int_least32_t > atomic_int_least32_t
atomic_int_least32_t
Definition atomic:1189
atomic< uint8_t > atomic_uint8_t
atomic_uint8_t
Definition atomic:1155
#define ATOMIC_BOOL_LOCK_FREE
atomic< wchar_t > atomic_wchar_t
atomic_wchar_t
Definition atomic:1134
atomic< unsigned int > atomic_uint
atomic_uint
Definition atomic:1119
atomic< uint_least32_t > atomic_uint_least32_t
atomic_uint_least32_t
Definition atomic:1192
atomic< uint_fast64_t > atomic_uint_fast64_t
atomic_uint_fast64_t
Definition atomic:1223
atomic< int_fast32_t > atomic_int_fast32_t
atomic_int_fast32_t
Definition atomic:1214
atomic< char > atomic_char
atomic_char
Definition atomic:1101
atomic< int > atomic_int
atomic_int
Definition atomic:1116
atomic< uint_least64_t > atomic_uint_least64_t
atomic_uint_least64_t
Definition atomic:1198
atomic< int64_t > atomic_int64_t
atomic_int64_t
Definition atomic:1170
atomic< uintmax_t > atomic_uintmax_t
atomic_uintmax_t
Definition atomic:1242
atomic< int_fast16_t > atomic_int_fast16_t
atomic_int_fast16_t
Definition atomic:1208
atomic< int32_t > atomic_int32_t
atomic_int32_t
Definition atomic:1164
atomic< uint_fast16_t > atomic_uint_fast16_t
atomic_uint_fast16_t
Definition atomic:1211
atomic< int8_t > atomic_int8_t
atomic_int8_t
Definition atomic:1152
atomic< long long > atomic_llong
atomic_llong
Definition atomic:1128
atomic< char16_t > atomic_char16_t
atomic_char16_t
Definition atomic:1142
atomic< int_fast64_t > atomic_int_fast64_t
atomic_int_fast64_t
Definition atomic:1220
atomic< ptrdiff_t > atomic_ptrdiff_t
atomic_ptrdiff_t
Definition atomic:1236
atomic< char32_t > atomic_char32_t
atomic_char32_t
Definition atomic:1145
atomic< int_least16_t > atomic_int_least16_t
atomic_int_least16_t
Definition atomic:1183
atomic< unsigned char > atomic_uchar
atomic_uchar
Definition atomic:1107
atomic< int_fast8_t > atomic_int_fast8_t
atomic_int_fast8_t
Definition atomic:1202
memory_order
Enumeration for memory_order.
Definition atomic_base.h:66
atomic< unsigned short > atomic_ushort
atomic_ushort
Definition atomic:1113
atomic< int_least64_t > atomic_int_least64_t
atomic_int_least64_t
Definition atomic:1195
atomic< bool > atomic_bool
atomic_bool
Definition atomic:1098
atomic< uint_fast32_t > atomic_uint_fast32_t
atomic_uint_fast32_t
Definition atomic:1217
atomic< uint32_t > atomic_uint32_t
atomic_uint32_t
Definition atomic:1167
ISO C++ entities toplevel namespace is std.
Generic atomic type, primary class template.
Definition atomic:201
atomic_flag