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
723
724 /// Explicit specialization for char.
725 template<>
726 struct atomic<char> : __atomic_base<char>
727 {
728 typedef char __integral_type;
729 typedef __atomic_base<char> __base_type;
730
731 atomic() noexcept = default;
732 ~atomic() noexcept = default;
733 atomic(const atomic&) = delete;
734 atomic& operator=(const atomic&) = delete;
735 atomic& operator=(const atomic&) volatile = delete;
736
737 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
738
739 using __base_type::operator __integral_type;
740 using __base_type::operator=;
741
742#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
743 static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2;
744#endif
745 };
746
747 /// Explicit specialization for signed char.
748 template<>
749 struct atomic<signed char> : __atomic_base<signed char>
750 {
751 typedef signed char __integral_type;
752 typedef __atomic_base<signed char> __base_type;
753
754 atomic() noexcept= default;
755 ~atomic() noexcept = default;
756 atomic(const atomic&) = delete;
757 atomic& operator=(const atomic&) = delete;
758 atomic& operator=(const atomic&) volatile = delete;
759
760 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
761
762 using __base_type::operator __integral_type;
763 using __base_type::operator=;
764
765#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
766 static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2;
767#endif
768 };
769
770 /// Explicit specialization for unsigned char.
771 template<>
772 struct atomic<unsigned char> : __atomic_base<unsigned char>
773 {
774 typedef unsigned char __integral_type;
775 typedef __atomic_base<unsigned char> __base_type;
776
777 atomic() noexcept= default;
778 ~atomic() noexcept = default;
779 atomic(const atomic&) = delete;
780 atomic& operator=(const atomic&) = delete;
781 atomic& operator=(const atomic&) volatile = delete;
782
783 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
784
785 using __base_type::operator __integral_type;
786 using __base_type::operator=;
787
788#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
789 static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2;
790#endif
791 };
792
793 /// Explicit specialization for short.
794 template<>
795 struct atomic<short> : __atomic_base<short>
796 {
797 typedef short __integral_type;
798 typedef __atomic_base<short> __base_type;
799
800 atomic() noexcept = default;
801 ~atomic() noexcept = default;
802 atomic(const atomic&) = delete;
803 atomic& operator=(const atomic&) = delete;
804 atomic& operator=(const atomic&) volatile = delete;
805
806 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
807
808 using __base_type::operator __integral_type;
809 using __base_type::operator=;
810
811#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
812 static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2;
813#endif
814 };
815
816 /// Explicit specialization for unsigned short.
817 template<>
818 struct atomic<unsigned short> : __atomic_base<unsigned short>
819 {
820 typedef unsigned short __integral_type;
821 typedef __atomic_base<unsigned short> __base_type;
822
823 atomic() noexcept = default;
824 ~atomic() noexcept = default;
825 atomic(const atomic&) = delete;
826 atomic& operator=(const atomic&) = delete;
827 atomic& operator=(const atomic&) volatile = delete;
828
829 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
830
831 using __base_type::operator __integral_type;
832 using __base_type::operator=;
833
834#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
835 static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2;
836#endif
837 };
838
839 /// Explicit specialization for int.
840 template<>
841 struct atomic<int> : __atomic_base<int>
842 {
843 typedef int __integral_type;
844 typedef __atomic_base<int> __base_type;
845
846 atomic() noexcept = default;
847 ~atomic() noexcept = default;
848 atomic(const atomic&) = delete;
849 atomic& operator=(const atomic&) = delete;
850 atomic& operator=(const atomic&) volatile = delete;
851
852 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
853
854 using __base_type::operator __integral_type;
855 using __base_type::operator=;
856
857#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
858 static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2;
859#endif
860 };
861
862 /// Explicit specialization for unsigned int.
863 template<>
864 struct atomic<unsigned int> : __atomic_base<unsigned int>
865 {
866 typedef unsigned int __integral_type;
867 typedef __atomic_base<unsigned int> __base_type;
868
869 atomic() noexcept = default;
870 ~atomic() noexcept = default;
871 atomic(const atomic&) = delete;
872 atomic& operator=(const atomic&) = delete;
873 atomic& operator=(const atomic&) volatile = delete;
874
875 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
876
877 using __base_type::operator __integral_type;
878 using __base_type::operator=;
879
880#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
881 static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2;
882#endif
883 };
884
885 /// Explicit specialization for long.
886 template<>
887 struct atomic<long> : __atomic_base<long>
888 {
889 typedef long __integral_type;
890 typedef __atomic_base<long> __base_type;
891
892 atomic() noexcept = default;
893 ~atomic() noexcept = default;
894 atomic(const atomic&) = delete;
895 atomic& operator=(const atomic&) = delete;
896 atomic& operator=(const atomic&) volatile = delete;
897
898 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
899
900 using __base_type::operator __integral_type;
901 using __base_type::operator=;
902
903#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
904 static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2;
905#endif
906 };
907
908 /// Explicit specialization for unsigned long.
909 template<>
910 struct atomic<unsigned long> : __atomic_base<unsigned long>
911 {
912 typedef unsigned long __integral_type;
913 typedef __atomic_base<unsigned long> __base_type;
914
915 atomic() noexcept = default;
916 ~atomic() noexcept = default;
917 atomic(const atomic&) = delete;
918 atomic& operator=(const atomic&) = delete;
919 atomic& operator=(const atomic&) volatile = delete;
920
921 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
922
923 using __base_type::operator __integral_type;
924 using __base_type::operator=;
925
926#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
927 static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2;
928#endif
929 };
930
931 /// Explicit specialization for long long.
932 template<>
933 struct atomic<long long> : __atomic_base<long long>
934 {
935 typedef long long __integral_type;
936 typedef __atomic_base<long long> __base_type;
937
938 atomic() noexcept = default;
939 ~atomic() noexcept = default;
940 atomic(const atomic&) = delete;
941 atomic& operator=(const atomic&) = delete;
942 atomic& operator=(const atomic&) volatile = delete;
943
944 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
945
946 using __base_type::operator __integral_type;
947 using __base_type::operator=;
948
949#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
950 static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2;
951#endif
952 };
953
954 /// Explicit specialization for unsigned long long.
955 template<>
956 struct atomic<unsigned long long> : __atomic_base<unsigned long long>
957 {
958 typedef unsigned long long __integral_type;
959 typedef __atomic_base<unsigned long long> __base_type;
960
961 atomic() noexcept = default;
962 ~atomic() noexcept = default;
963 atomic(const atomic&) = delete;
964 atomic& operator=(const atomic&) = delete;
965 atomic& operator=(const atomic&) volatile = delete;
966
967 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
968
969 using __base_type::operator __integral_type;
970 using __base_type::operator=;
971
972#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
973 static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2;
974#endif
975 };
976
977 /// Explicit specialization for wchar_t.
978 template<>
979 struct atomic<wchar_t> : __atomic_base<wchar_t>
980 {
981 typedef wchar_t __integral_type;
982 typedef __atomic_base<wchar_t> __base_type;
983
984 atomic() noexcept = default;
985 ~atomic() noexcept = default;
986 atomic(const atomic&) = delete;
987 atomic& operator=(const atomic&) = delete;
988 atomic& operator=(const atomic&) volatile = delete;
989
990 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
991
992 using __base_type::operator __integral_type;
993 using __base_type::operator=;
994
995#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
996 static constexpr bool is_always_lock_free = ATOMIC_WCHAR_T_LOCK_FREE == 2;
997#endif
998 };
999
1000#ifdef _GLIBCXX_USE_CHAR8_T
1001 /// Explicit specialization for char8_t.
1002 template<>
1003 struct atomic<char8_t> : __atomic_base<char8_t>
1004 {
1005 typedef char8_t __integral_type;
1006 typedef __atomic_base<char8_t> __base_type;
1007
1008 atomic() noexcept = default;
1009 ~atomic() noexcept = default;
1010 atomic(const atomic&) = delete;
1011 atomic& operator=(const atomic&) = delete;
1012 atomic& operator=(const atomic&) volatile = delete;
1013
1014 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
1015
1016 using __base_type::operator __integral_type;
1017 using __base_type::operator=;
1018
1019#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
1020 static constexpr bool is_always_lock_free
1021 = ATOMIC_CHAR8_T_LOCK_FREE == 2;
1022#endif
1023 };
1024#endif
1025
1026 /// Explicit specialization for char16_t.
1027 template<>
1028 struct atomic<char16_t> : __atomic_base<char16_t>
1029 {
1030 typedef char16_t __integral_type;
1031 typedef __atomic_base<char16_t> __base_type;
1032
1033 atomic() noexcept = default;
1034 ~atomic() noexcept = default;
1035 atomic(const atomic&) = delete;
1036 atomic& operator=(const atomic&) = delete;
1037 atomic& operator=(const atomic&) volatile = delete;
1038
1039 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
1040
1041 using __base_type::operator __integral_type;
1042 using __base_type::operator=;
1043
1044#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
1045 static constexpr bool is_always_lock_free
1046 = ATOMIC_CHAR16_T_LOCK_FREE == 2;
1047#endif
1048 };
1049
1050 /// Explicit specialization for char32_t.
1051 template<>
1052 struct atomic<char32_t> : __atomic_base<char32_t>
1053 {
1054 typedef char32_t __integral_type;
1055 typedef __atomic_base<char32_t> __base_type;
1056
1057 atomic() noexcept = default;
1058 ~atomic() noexcept = default;
1059 atomic(const atomic&) = delete;
1060 atomic& operator=(const atomic&) = delete;
1061 atomic& operator=(const atomic&) volatile = delete;
1062
1063 constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { }
1064
1065 using __base_type::operator __integral_type;
1066 using __base_type::operator=;
1067
1068#ifdef __cpp_lib_atomic_is_always_lock_free // C++ >= 17
1069 static constexpr bool is_always_lock_free
1070 = ATOMIC_CHAR32_T_LOCK_FREE == 2;
1071#endif
1072 };
1073
1074
1075 /// atomic_bool
1077
1078 /// atomic_char
1080
1081 /// atomic_schar
1083
1084 /// atomic_uchar
1086
1087 /// atomic_short
1089
1090 /// atomic_ushort
1092
1093 /// atomic_int
1095
1096 /// atomic_uint
1098
1099 /// atomic_long
1101
1102 /// atomic_ulong
1104
1105 /// atomic_llong
1107
1108 /// atomic_ullong
1110
1111 /// atomic_wchar_t
1113
1114#ifdef _GLIBCXX_USE_CHAR8_T
1115 /// atomic_char8_t
1116 typedef atomic<char8_t> atomic_char8_t;
1117#endif
1118
1119 /// atomic_char16_t
1121
1122 /// atomic_char32_t
1124
1125#ifdef _GLIBCXX_USE_C99_STDINT
1126 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1127 // 2441. Exact-width atomic typedefs should be provided
1128
1129 /// atomic_int8_t
1131
1132 /// atomic_uint8_t
1134
1135 /// atomic_int16_t
1137
1138 /// atomic_uint16_t
1140
1141 /// atomic_int32_t
1143
1144 /// atomic_uint32_t
1146
1147 /// atomic_int64_t
1149
1150 /// atomic_uint64_t
1152#endif
1153
1154 /// atomic_int_least8_t
1156
1157 /// atomic_uint_least8_t
1159
1160 /// atomic_int_least16_t
1162
1163 /// atomic_uint_least16_t
1165
1166 /// atomic_int_least32_t
1168
1169 /// atomic_uint_least32_t
1171
1172 /// atomic_int_least64_t
1174
1175 /// atomic_uint_least64_t
1177
1178
1179 /// atomic_int_fast8_t
1181
1182 /// atomic_uint_fast8_t
1184
1185 /// atomic_int_fast16_t
1187
1188 /// atomic_uint_fast16_t
1190
1191 /// atomic_int_fast32_t
1193
1194 /// atomic_uint_fast32_t
1196
1197 /// atomic_int_fast64_t
1199
1200 /// atomic_uint_fast64_t
1202
1203
1204 /// atomic_intptr_t
1206
1207 /// atomic_uintptr_t
1209
1210 /// atomic_size_t
1212
1213 /// atomic_ptrdiff_t
1215
1216 /// atomic_intmax_t
1218
1219 /// atomic_uintmax_t
1221
1222 // Function definitions, atomic_flag operations.
1223 inline bool
1224 atomic_flag_test_and_set_explicit(atomic_flag* __a,
1225 memory_order __m) noexcept
1226 { return __a->test_and_set(__m); }
1227
1228 inline bool
1229 atomic_flag_test_and_set_explicit(volatile atomic_flag* __a,
1230 memory_order __m) noexcept
1231 { return __a->test_and_set(__m); }
1232
1233#if __cpp_lib_atomic_flag_test
1234 inline bool
1235 atomic_flag_test(const atomic_flag* __a) noexcept
1236 { return __a->test(); }
1237
1238 inline bool
1239 atomic_flag_test(const volatile atomic_flag* __a) noexcept
1240 { return __a->test(); }
1241
1242 inline bool
1243 atomic_flag_test_explicit(const atomic_flag* __a,
1244 memory_order __m) noexcept
1245 { return __a->test(__m); }
1246
1247 inline bool
1248 atomic_flag_test_explicit(const volatile atomic_flag* __a,
1249 memory_order __m) noexcept
1250 { return __a->test(__m); }
1251#endif
1252
1253 inline void
1254 atomic_flag_clear_explicit(atomic_flag* __a, memory_order __m) noexcept
1255 { __a->clear(__m); }
1256
1257 inline void
1258 atomic_flag_clear_explicit(volatile atomic_flag* __a,
1259 memory_order __m) noexcept
1260 { __a->clear(__m); }
1261
1262 inline bool
1263 atomic_flag_test_and_set(atomic_flag* __a) noexcept
1264 { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); }
1265
1266 inline bool
1267 atomic_flag_test_and_set(volatile atomic_flag* __a) noexcept
1268 { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); }
1269
1270 inline void
1271 atomic_flag_clear(atomic_flag* __a) noexcept
1272 { atomic_flag_clear_explicit(__a, memory_order_seq_cst); }
1273
1274 inline void
1275 atomic_flag_clear(volatile atomic_flag* __a) noexcept
1276 { atomic_flag_clear_explicit(__a, memory_order_seq_cst); }
1277
1278#if __cpp_lib_atomic_wait
1279 inline void
1280 atomic_flag_wait(atomic_flag* __a, bool __old) noexcept
1281 { __a->wait(__old); }
1282
1283 inline void
1284 atomic_flag_wait_explicit(atomic_flag* __a, bool __old,
1285 memory_order __m) noexcept
1286 { __a->wait(__old, __m); }
1287
1288 inline void
1289 atomic_flag_notify_one(atomic_flag* __a) noexcept
1290 { __a->notify_one(); }
1291
1292 inline void
1293 atomic_flag_notify_all(atomic_flag* __a) noexcept
1294 { __a->notify_all(); }
1295#endif // __cpp_lib_atomic_wait
1296
1297 /// @cond undocumented
1298 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1299 // 3220. P0558 broke conforming C++14 uses of atomic shared_ptr
1300 template<typename _Tp>
1301 using __atomic_val_t = __type_identity_t<_Tp>;
1302 template<typename _Tp>
1303 using __atomic_diff_t = typename atomic<_Tp>::difference_type;
1304 /// @endcond
1305
1306 // [atomics.nonmembers] Non-member functions.
1307 // Function templates generally applicable to atomic types.
1308 template<typename _ITp>
1309 inline bool
1310 atomic_is_lock_free(const atomic<_ITp>* __a) noexcept
1311 { return __a->is_lock_free(); }
1312
1313 template<typename _ITp>
1314 inline bool
1315 atomic_is_lock_free(const volatile atomic<_ITp>* __a) noexcept
1316 { return __a->is_lock_free(); }
1317
1318 template<typename _ITp>
1319 inline void
1320 atomic_init(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept
1321 { __a->store(__i, memory_order_relaxed); }
1322
1323 template<typename _ITp>
1324 inline void
1325 atomic_init(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept
1326 { __a->store(__i, memory_order_relaxed); }
1327
1328 template<typename _ITp>
1329 inline void
1330 atomic_store_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i,
1331 memory_order __m) noexcept
1332 { __a->store(__i, __m); }
1333
1334 template<typename _ITp>
1335 inline void
1336 atomic_store_explicit(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i,
1337 memory_order __m) noexcept
1338 { __a->store(__i, __m); }
1339
1340 template<typename _ITp>
1341 inline _ITp
1342 atomic_load_explicit(const atomic<_ITp>* __a, memory_order __m) noexcept
1343 { return __a->load(__m); }
1344
1345 template<typename _ITp>
1346 inline _ITp
1347 atomic_load_explicit(const volatile atomic<_ITp>* __a,
1348 memory_order __m) noexcept
1349 { return __a->load(__m); }
1350
1351 template<typename _ITp>
1352 inline _ITp
1353 atomic_exchange_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i,
1354 memory_order __m) noexcept
1355 { return __a->exchange(__i, __m); }
1356
1357 template<typename _ITp>
1358 inline _ITp
1359 atomic_exchange_explicit(volatile atomic<_ITp>* __a,
1360 __atomic_val_t<_ITp> __i,
1361 memory_order __m) noexcept
1362 { return __a->exchange(__i, __m); }
1363
1364 template<typename _ITp>
1365 inline bool
1366 atomic_compare_exchange_weak_explicit(atomic<_ITp>* __a,
1367 __atomic_val_t<_ITp>* __i1,
1368 __atomic_val_t<_ITp> __i2,
1369 memory_order __m1,
1370 memory_order __m2) noexcept
1371 { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); }
1372
1373 template<typename _ITp>
1374 inline bool
1375 atomic_compare_exchange_weak_explicit(volatile atomic<_ITp>* __a,
1376 __atomic_val_t<_ITp>* __i1,
1377 __atomic_val_t<_ITp> __i2,
1378 memory_order __m1,
1379 memory_order __m2) noexcept
1380 { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); }
1381
1382 template<typename _ITp>
1383 inline bool
1384 atomic_compare_exchange_strong_explicit(atomic<_ITp>* __a,
1385 __atomic_val_t<_ITp>* __i1,
1386 __atomic_val_t<_ITp> __i2,
1387 memory_order __m1,
1388 memory_order __m2) noexcept
1389 { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); }
1390
1391 template<typename _ITp>
1392 inline bool
1393 atomic_compare_exchange_strong_explicit(volatile atomic<_ITp>* __a,
1394 __atomic_val_t<_ITp>* __i1,
1395 __atomic_val_t<_ITp> __i2,
1396 memory_order __m1,
1397 memory_order __m2) noexcept
1398 { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); }
1399
1400
1401 template<typename _ITp>
1402 inline void
1403 atomic_store(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept
1404 { atomic_store_explicit(__a, __i, memory_order_seq_cst); }
1405
1406 template<typename _ITp>
1407 inline void
1408 atomic_store(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept
1409 { atomic_store_explicit(__a, __i, memory_order_seq_cst); }
1410
1411 template<typename _ITp>
1412 inline _ITp
1413 atomic_load(const atomic<_ITp>* __a) noexcept
1414 { return atomic_load_explicit(__a, memory_order_seq_cst); }
1415
1416 template<typename _ITp>
1417 inline _ITp
1418 atomic_load(const volatile atomic<_ITp>* __a) noexcept
1419 { return atomic_load_explicit(__a, memory_order_seq_cst); }
1420
1421 template<typename _ITp>
1422 inline _ITp
1423 atomic_exchange(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept
1424 { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); }
1425
1426 template<typename _ITp>
1427 inline _ITp
1428 atomic_exchange(volatile atomic<_ITp>* __a,
1429 __atomic_val_t<_ITp> __i) noexcept
1430 { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); }
1431
1432 template<typename _ITp>
1433 inline bool
1434 atomic_compare_exchange_weak(atomic<_ITp>* __a,
1435 __atomic_val_t<_ITp>* __i1,
1436 __atomic_val_t<_ITp> __i2) noexcept
1437 {
1438 return atomic_compare_exchange_weak_explicit(__a, __i1, __i2,
1439 memory_order_seq_cst,
1440 memory_order_seq_cst);
1441 }
1442
1443 template<typename _ITp>
1444 inline bool
1445 atomic_compare_exchange_weak(volatile atomic<_ITp>* __a,
1446 __atomic_val_t<_ITp>* __i1,
1447 __atomic_val_t<_ITp> __i2) noexcept
1448 {
1449 return atomic_compare_exchange_weak_explicit(__a, __i1, __i2,
1450 memory_order_seq_cst,
1451 memory_order_seq_cst);
1452 }
1453
1454 template<typename _ITp>
1455 inline bool
1456 atomic_compare_exchange_strong(atomic<_ITp>* __a,
1457 __atomic_val_t<_ITp>* __i1,
1458 __atomic_val_t<_ITp> __i2) noexcept
1459 {
1460 return atomic_compare_exchange_strong_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_strong(volatile atomic<_ITp>* __a,
1468 __atomic_val_t<_ITp>* __i1,
1469 __atomic_val_t<_ITp> __i2) noexcept
1470 {
1471 return atomic_compare_exchange_strong_explicit(__a, __i1, __i2,
1472 memory_order_seq_cst,
1473 memory_order_seq_cst);
1474 }
1475
1476
1477#if __cpp_lib_atomic_wait
1478 template<typename _Tp>
1479 inline void
1480 atomic_wait(const atomic<_Tp>* __a,
1481 typename std::atomic<_Tp>::value_type __old) noexcept
1482 { __a->wait(__old); }
1483
1484 template<typename _Tp>
1485 inline void
1486 atomic_wait_explicit(const atomic<_Tp>* __a,
1487 typename std::atomic<_Tp>::value_type __old,
1488 std::memory_order __m) noexcept
1489 { __a->wait(__old, __m); }
1490
1491 template<typename _Tp>
1492 inline void
1493 atomic_notify_one(atomic<_Tp>* __a) noexcept
1494 { __a->notify_one(); }
1495
1496 template<typename _Tp>
1497 inline void
1498 atomic_notify_all(atomic<_Tp>* __a) noexcept
1499 { __a->notify_all(); }
1500#endif // __cpp_lib_atomic_wait
1501
1502 // Function templates for atomic_integral and atomic_pointer operations only.
1503 // Some operations (and, or, xor) are only available for atomic integrals,
1504 // which is implemented by taking a parameter of type __atomic_base<_ITp>*.
1505
1506 template<typename _ITp>
1507 inline _ITp
1508 atomic_fetch_add_explicit(atomic<_ITp>* __a,
1509 __atomic_diff_t<_ITp> __i,
1510 memory_order __m) noexcept
1511 { return __a->fetch_add(__i, __m); }
1512
1513 template<typename _ITp>
1514 inline _ITp
1515 atomic_fetch_add_explicit(volatile atomic<_ITp>* __a,
1516 __atomic_diff_t<_ITp> __i,
1517 memory_order __m) noexcept
1518 { return __a->fetch_add(__i, __m); }
1519
1520 template<typename _ITp>
1521 inline _ITp
1522 atomic_fetch_sub_explicit(atomic<_ITp>* __a,
1523 __atomic_diff_t<_ITp> __i,
1524 memory_order __m) noexcept
1525 { return __a->fetch_sub(__i, __m); }
1526
1527 template<typename _ITp>
1528 inline _ITp
1529 atomic_fetch_sub_explicit(volatile atomic<_ITp>* __a,
1530 __atomic_diff_t<_ITp> __i,
1531 memory_order __m) noexcept
1532 { return __a->fetch_sub(__i, __m); }
1533
1534 template<typename _ITp>
1535 inline _ITp
1536 atomic_fetch_and_explicit(__atomic_base<_ITp>* __a,
1537 __atomic_val_t<_ITp> __i,
1538 memory_order __m) noexcept
1539 { return __a->fetch_and(__i, __m); }
1540
1541 template<typename _ITp>
1542 inline _ITp
1543 atomic_fetch_and_explicit(volatile __atomic_base<_ITp>* __a,
1544 __atomic_val_t<_ITp> __i,
1545 memory_order __m) noexcept
1546 { return __a->fetch_and(__i, __m); }
1547
1548 template<typename _ITp>
1549 inline _ITp
1550 atomic_fetch_or_explicit(__atomic_base<_ITp>* __a,
1551 __atomic_val_t<_ITp> __i,
1552 memory_order __m) noexcept
1553 { return __a->fetch_or(__i, __m); }
1554
1555 template<typename _ITp>
1556 inline _ITp
1557 atomic_fetch_or_explicit(volatile __atomic_base<_ITp>* __a,
1558 __atomic_val_t<_ITp> __i,
1559 memory_order __m) noexcept
1560 { return __a->fetch_or(__i, __m); }
1561
1562 template<typename _ITp>
1563 inline _ITp
1564 atomic_fetch_xor_explicit(__atomic_base<_ITp>* __a,
1565 __atomic_val_t<_ITp> __i,
1566 memory_order __m) noexcept
1567 { return __a->fetch_xor(__i, __m); }
1568
1569 template<typename _ITp>
1570 inline _ITp
1571 atomic_fetch_xor_explicit(volatile __atomic_base<_ITp>* __a,
1572 __atomic_val_t<_ITp> __i,
1573 memory_order __m) noexcept
1574 { return __a->fetch_xor(__i, __m); }
1575
1576#ifdef __cpp_lib_atomic_min_max
1577 template<typename _ITp>
1578 inline _ITp
1579 atomic_fetch_min_explicit(__atomic_base<_ITp>* __a,
1580 __atomic_val_t<_ITp> __i,
1581 memory_order __m) noexcept
1582 { return __a->fetch_min(__i, __m); }
1583
1584 template<typename _ITp>
1585 inline _ITp
1586 atomic_fetch_min_explicit(volatile __atomic_base<_ITp>* __a,
1587 __atomic_val_t<_ITp> __i,
1588 memory_order __m) noexcept
1589 { return __a->fetch_min(__i, __m); }
1590
1591 template<typename _ITp>
1592 inline _ITp
1593 atomic_fetch_max_explicit(__atomic_base<_ITp>* __a,
1594 __atomic_val_t<_ITp> __i,
1595 memory_order __m) noexcept
1596 { return __a->fetch_max(__i, __m); }
1597
1598 template<typename _ITp>
1599 inline _ITp
1600 atomic_fetch_max_explicit(volatile __atomic_base<_ITp>* __a,
1601 __atomic_val_t<_ITp> __i,
1602 memory_order __m) noexcept
1603 { return __a->fetch_max(__i, __m); }
1604#endif
1605
1606 template<typename _ITp>
1607 inline _ITp
1608 atomic_fetch_add(atomic<_ITp>* __a,
1609 __atomic_diff_t<_ITp> __i) noexcept
1610 { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); }
1611
1612 template<typename _ITp>
1613 inline _ITp
1614 atomic_fetch_add(volatile atomic<_ITp>* __a,
1615 __atomic_diff_t<_ITp> __i) noexcept
1616 { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); }
1617
1618 template<typename _ITp>
1619 inline _ITp
1620 atomic_fetch_sub(atomic<_ITp>* __a,
1621 __atomic_diff_t<_ITp> __i) noexcept
1622 { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); }
1623
1624 template<typename _ITp>
1625 inline _ITp
1626 atomic_fetch_sub(volatile atomic<_ITp>* __a,
1627 __atomic_diff_t<_ITp> __i) noexcept
1628 { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); }
1629
1630 template<typename _ITp>
1631 inline _ITp
1632 atomic_fetch_and(__atomic_base<_ITp>* __a,
1633 __atomic_val_t<_ITp> __i) noexcept
1634 { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); }
1635
1636 template<typename _ITp>
1637 inline _ITp
1638 atomic_fetch_and(volatile __atomic_base<_ITp>* __a,
1639 __atomic_val_t<_ITp> __i) noexcept
1640 { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); }
1641
1642 template<typename _ITp>
1643 inline _ITp
1644 atomic_fetch_or(__atomic_base<_ITp>* __a,
1645 __atomic_val_t<_ITp> __i) noexcept
1646 { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); }
1647
1648 template<typename _ITp>
1649 inline _ITp
1650 atomic_fetch_or(volatile __atomic_base<_ITp>* __a,
1651 __atomic_val_t<_ITp> __i) noexcept
1652 { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); }
1653
1654 template<typename _ITp>
1655 inline _ITp
1656 atomic_fetch_xor(__atomic_base<_ITp>* __a,
1657 __atomic_val_t<_ITp> __i) noexcept
1658 { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); }
1659
1660 template<typename _ITp>
1661 inline _ITp
1662 atomic_fetch_xor(volatile __atomic_base<_ITp>* __a,
1663 __atomic_val_t<_ITp> __i) noexcept
1664 { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); }
1665
1666#ifdef __cpp_lib_atomic_min_max
1667 template<typename _ITp>
1668 inline _ITp
1669 atomic_fetch_min(__atomic_base<_ITp>* __a,
1670 __atomic_val_t<_ITp> __i) noexcept
1671 { return atomic_fetch_min_explicit(__a, __i, memory_order_seq_cst); }
1672
1673 template<typename _ITp>
1674 inline _ITp
1675 atomic_fetch_min(volatile __atomic_base<_ITp>* __a,
1676 __atomic_val_t<_ITp> __i) noexcept
1677 { return atomic_fetch_min_explicit(__a, __i, memory_order_seq_cst); }
1678
1679 template<typename _ITp>
1680 inline _ITp
1681 atomic_fetch_max(__atomic_base<_ITp>* __a,
1682 __atomic_val_t<_ITp> __i) noexcept
1683 { return atomic_fetch_max_explicit(__a, __i, memory_order_seq_cst); }
1684
1685 template<typename _ITp>
1686 inline _ITp
1687 atomic_fetch_max(volatile __atomic_base<_ITp>* __a,
1688 __atomic_val_t<_ITp> __i) noexcept
1689 { return atomic_fetch_max_explicit(__a, __i, memory_order_seq_cst); }
1690#endif
1691
1692#ifdef __cpp_lib_atomic_float
1693 template<>
1694 struct atomic<float> : __atomic_float<float>
1695 {
1696 atomic() noexcept = default;
1697
1698 constexpr
1699 atomic(float __fp) noexcept : __atomic_float<float>(__fp)
1700 { }
1701
1702 atomic& operator=(const atomic&) volatile = delete;
1703 atomic& operator=(const atomic&) = delete;
1704
1705 using __atomic_float<float>::operator=;
1706 };
1707
1708 template<>
1709 struct atomic<double> : __atomic_float<double>
1710 {
1711 atomic() noexcept = default;
1712
1713 constexpr
1714 atomic(double __fp) noexcept : __atomic_float<double>(__fp)
1715 { }
1716
1717 atomic& operator=(const atomic&) volatile = delete;
1718 atomic& operator=(const atomic&) = delete;
1719
1720 using __atomic_float<double>::operator=;
1721 };
1722
1723 template<>
1724 struct atomic<long double> : __atomic_float<long double>
1725 {
1726 atomic() noexcept = default;
1727
1728 constexpr
1729 atomic(long double __fp) noexcept : __atomic_float<long double>(__fp)
1730 { }
1731
1732 atomic& operator=(const atomic&) volatile = delete;
1733 atomic& operator=(const atomic&) = delete;
1734
1735 using __atomic_float<long double>::operator=;
1736 };
1737
1738#ifdef __STDCPP_FLOAT16_T__
1739 template<>
1740 struct atomic<_Float16> : __atomic_float<_Float16>
1741 {
1742 atomic() noexcept = default;
1743
1744 constexpr
1745 atomic(_Float16 __fp) noexcept : __atomic_float<_Float16>(__fp)
1746 { }
1747
1748 atomic& operator=(const atomic&) volatile = delete;
1749 atomic& operator=(const atomic&) = delete;
1750
1751 using __atomic_float<_Float16>::operator=;
1752 };
1753#endif
1754
1755#ifdef __STDCPP_FLOAT32_T__
1756 template<>
1757 struct atomic<_Float32> : __atomic_float<_Float32>
1758 {
1759 atomic() noexcept = default;
1760
1761 constexpr
1762 atomic(_Float32 __fp) noexcept : __atomic_float<_Float32>(__fp)
1763 { }
1764
1765 atomic& operator=(const atomic&) volatile = delete;
1766 atomic& operator=(const atomic&) = delete;
1767
1768 using __atomic_float<_Float32>::operator=;
1769 };
1770#endif
1771
1772#ifdef __STDCPP_FLOAT64_T__
1773 template<>
1774 struct atomic<_Float64> : __atomic_float<_Float64>
1775 {
1776 atomic() noexcept = default;
1777
1778 constexpr
1779 atomic(_Float64 __fp) noexcept : __atomic_float<_Float64>(__fp)
1780 { }
1781
1782 atomic& operator=(const atomic&) volatile = delete;
1783 atomic& operator=(const atomic&) = delete;
1784
1785 using __atomic_float<_Float64>::operator=;
1786 };
1787#endif
1788
1789#ifdef __STDCPP_FLOAT128_T__
1790 template<>
1791 struct atomic<_Float128> : __atomic_float<_Float128>
1792 {
1793 atomic() noexcept = default;
1794
1795 constexpr
1796 atomic(_Float128 __fp) noexcept : __atomic_float<_Float128>(__fp)
1797 { }
1798
1799 atomic& operator=(const atomic&) volatile = delete;
1800 atomic& operator=(const atomic&) = delete;
1801
1802 using __atomic_float<_Float128>::operator=;
1803 };
1804#endif
1805
1806#ifdef __STDCPP_BFLOAT16_T__
1807 template<>
1808 struct atomic<__gnu_cxx::__bfloat16_t> : __atomic_float<__gnu_cxx::__bfloat16_t>
1809 {
1810 atomic() noexcept = default;
1811
1812 constexpr
1813 atomic(__gnu_cxx::__bfloat16_t __fp) noexcept : __atomic_float<__gnu_cxx::__bfloat16_t>(__fp)
1814 { }
1815
1816 atomic& operator=(const atomic&) volatile = delete;
1817 atomic& operator=(const atomic&) = delete;
1818
1819 using __atomic_float<__gnu_cxx::__bfloat16_t>::operator=;
1820 };
1821#endif
1822#endif // __cpp_lib_atomic_float
1823
1824#ifdef __cpp_lib_atomic_ref
1825 /// Class template to provide atomic operations on a non-atomic variable.
1826 template<typename _Tp>
1827 struct atomic_ref : __atomic_ref<_Tp>
1828 {
1829 explicit
1830 atomic_ref(_Tp& __t) noexcept
1831 : __atomic_ref<_Tp>(std::addressof(__t))
1832 {
1833 __glibcxx_assert(((__UINTPTR_TYPE__)this->_M_ptr % this->required_alignment) == 0);
1834 }
1835
1836 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1837 // 4472. std::atomic_ref<const T> can be constructed from temporaries
1838 explicit
1839 atomic_ref(_Tp&&) = delete;
1840
1841 template<typename _Up>
1842 requires is_convertible_v<_Up(*)[1], _Tp(*)[1]>
1843 atomic_ref(atomic_ref<_Up> __other) noexcept
1844 : __atomic_ref<_Tp>(__other._M_ptr)
1845 { }
1846
1847 atomic_ref& operator=(const atomic_ref&) = delete;
1848
1849 atomic_ref(const atomic_ref&) = default;
1850
1851 using __atomic_ref<_Tp>::operator=;
1852
1853 template<typename>
1854 friend struct atomic_ref;
1855 };
1856#endif // __cpp_lib_atomic_ref
1857
1858#ifdef __cpp_lib_atomic_lock_free_type_aliases
1859# ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
1860 using atomic_signed_lock_free
1862 using atomic_unsigned_lock_free
1864# elif ATOMIC_INT_LOCK_FREE == 2
1865 using atomic_signed_lock_free = atomic<signed int>;
1866 using atomic_unsigned_lock_free = atomic<unsigned int>;
1867# elif ATOMIC_LONG_LOCK_FREE == 2
1868 using atomic_signed_lock_free = atomic<signed long>;
1869 using atomic_unsigned_lock_free = atomic<unsigned long>;
1870# elif ATOMIC_CHAR_LOCK_FREE == 2
1871 using atomic_signed_lock_free = atomic<signed char>;
1872 using atomic_unsigned_lock_free = atomic<unsigned char>;
1873# else
1874# error "libstdc++ bug: no lock-free atomics but they were emitted in <version>"
1875# endif
1876#endif
1877
1878 /// @} group atomics
1879
1880_GLIBCXX_END_NAMESPACE_VERSION
1881} // namespace
1882
1883#endif // C++11
1884
1885#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:1103
atomic< intmax_t > atomic_intmax_t
atomic_intmax_t
Definition atomic:1217
atomic< uintptr_t > atomic_uintptr_t
atomic_uintptr_t
Definition atomic:1208
atomic< signed char > atomic_schar
atomic_schar
Definition atomic:1082
atomic< int_least8_t > atomic_int_least8_t
atomic_int_least8_t
Definition atomic:1155
atomic< unsigned long long > atomic_ullong
atomic_ullong
Definition atomic:1109
atomic< uint_fast8_t > atomic_uint_fast8_t
atomic_uint_fast8_t
Definition atomic:1183
atomic< intptr_t > atomic_intptr_t
atomic_intptr_t
Definition atomic:1205
atomic< int16_t > atomic_int16_t
atomic_int16_t
Definition atomic:1136
atomic< size_t > atomic_size_t
atomic_size_t
Definition atomic:1211
atomic< long > atomic_long
atomic_long
Definition atomic:1100
atomic< uint_least8_t > atomic_uint_least8_t
atomic_uint_least8_t
Definition atomic:1158
atomic< short > atomic_short
atomic_short
Definition atomic:1088
atomic< uint_least16_t > atomic_uint_least16_t
atomic_uint_least16_t
Definition atomic:1164
atomic< uint16_t > atomic_uint16_t
atomic_uint16_t
Definition atomic:1139
atomic< uint64_t > atomic_uint64_t
atomic_uint64_t
Definition atomic:1151
atomic< int_least32_t > atomic_int_least32_t
atomic_int_least32_t
Definition atomic:1167
atomic< uint8_t > atomic_uint8_t
atomic_uint8_t
Definition atomic:1133
#define ATOMIC_BOOL_LOCK_FREE
atomic< wchar_t > atomic_wchar_t
atomic_wchar_t
Definition atomic:1112
atomic< unsigned int > atomic_uint
atomic_uint
Definition atomic:1097
atomic< uint_least32_t > atomic_uint_least32_t
atomic_uint_least32_t
Definition atomic:1170
atomic< uint_fast64_t > atomic_uint_fast64_t
atomic_uint_fast64_t
Definition atomic:1201
atomic< int_fast32_t > atomic_int_fast32_t
atomic_int_fast32_t
Definition atomic:1192
atomic< char > atomic_char
atomic_char
Definition atomic:1079
atomic< int > atomic_int
atomic_int
Definition atomic:1094
atomic< uint_least64_t > atomic_uint_least64_t
atomic_uint_least64_t
Definition atomic:1176
atomic< int64_t > atomic_int64_t
atomic_int64_t
Definition atomic:1148
atomic< uintmax_t > atomic_uintmax_t
atomic_uintmax_t
Definition atomic:1220
atomic< int_fast16_t > atomic_int_fast16_t
atomic_int_fast16_t
Definition atomic:1186
atomic< int32_t > atomic_int32_t
atomic_int32_t
Definition atomic:1142
atomic< uint_fast16_t > atomic_uint_fast16_t
atomic_uint_fast16_t
Definition atomic:1189
atomic< int8_t > atomic_int8_t
atomic_int8_t
Definition atomic:1130
atomic< long long > atomic_llong
atomic_llong
Definition atomic:1106
atomic< char16_t > atomic_char16_t
atomic_char16_t
Definition atomic:1120
atomic< int_fast64_t > atomic_int_fast64_t
atomic_int_fast64_t
Definition atomic:1198
atomic< ptrdiff_t > atomic_ptrdiff_t
atomic_ptrdiff_t
Definition atomic:1214
atomic< char32_t > atomic_char32_t
atomic_char32_t
Definition atomic:1123
atomic< int_least16_t > atomic_int_least16_t
atomic_int_least16_t
Definition atomic:1161
atomic< unsigned char > atomic_uchar
atomic_uchar
Definition atomic:1085
atomic< int_fast8_t > atomic_int_fast8_t
atomic_int_fast8_t
Definition atomic:1180
memory_order
Enumeration for memory_order.
Definition atomic_base.h:66
atomic< unsigned short > atomic_ushort
atomic_ushort
Definition atomic:1091
atomic< int_least64_t > atomic_int_least64_t
atomic_int_least64_t
Definition atomic:1173
atomic< bool > atomic_bool
atomic_bool
Definition atomic:1076
atomic< uint_fast32_t > atomic_uint_fast32_t
atomic_uint_fast32_t
Definition atomic:1195
atomic< uint32_t > atomic_uint32_t
atomic_uint32_t
Definition atomic:1145
ISO C++ entities toplevel namespace is std.
Generic atomic type, primary class template.
Definition atomic:201
atomic_flag