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