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