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