1 // -*- C++ -*- header.
2
3 // Copyright (C) 2008-2014 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 bits/atomic_base.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{atomic}
28 */
29
30 #ifndef _GLIBCXX_ATOMIC_BASE_H
31 #define _GLIBCXX_ATOMIC_BASE_H 1
32
33 #pragma GCC system_header
34
35 #include <bits/c++config.h>
36 #include <stdbool.h>
37 #include <stdint.h>
38 #include <bits/atomic_lockfree_defines.h>
39
40 #ifndef _GLIBCXX_ALWAYS_INLINE
41 #define _GLIBCXX_ALWAYS_INLINE inline __attribute__((always_inline))
42 #endif
43
_GLIBCXX_VISIBILITY(default)44 namespace std _GLIBCXX_VISIBILITY(default)
45 {
46 _GLIBCXX_BEGIN_NAMESPACE_VERSION
47
48 /**
49 * @defgroup atomics Atomics
50 *
51 * Components for performing atomic operations.
52 * @{
53 */
54
55 /// Enumeration for memory_order
56 typedef enum memory_order
57 {
58 memory_order_relaxed,
59 memory_order_consume,
60 memory_order_acquire,
61 memory_order_release,
62 memory_order_acq_rel,
63 memory_order_seq_cst
64 } memory_order;
65
66 enum __memory_order_modifier
67 {
68 __memory_order_mask = 0x0ffff,
69 __memory_order_modifier_mask = 0xffff0000,
70 __memory_order_hle_acquire = 0x10000,
71 __memory_order_hle_release = 0x20000
72 };
73
74 constexpr memory_order
75 operator|(memory_order __m, __memory_order_modifier __mod)
76 {
77 return memory_order(__m | int(__mod));
78 }
79
80 constexpr memory_order
81 operator&(memory_order __m, __memory_order_modifier __mod)
82 {
83 return memory_order(__m & int(__mod));
84 }
85
86 // Drop release ordering as per [atomics.types.operations.req]/21
87 constexpr memory_order
88 __cmpexch_failure_order2(memory_order __m) noexcept
89 {
90 return __m == memory_order_acq_rel ? memory_order_acquire
91 : __m == memory_order_release ? memory_order_relaxed : __m;
92 }
93
94 constexpr memory_order
95 __cmpexch_failure_order(memory_order __m) noexcept
96 {
97 return memory_order(__cmpexch_failure_order2(__m & __memory_order_mask)
98 | (__m & __memory_order_modifier_mask));
99 }
100
101 _GLIBCXX_ALWAYS_INLINE void
102 atomic_thread_fence(memory_order __m) noexcept
103 { __atomic_thread_fence(__m); }
104
105 _GLIBCXX_ALWAYS_INLINE void
106 atomic_signal_fence(memory_order __m) noexcept
107 { __atomic_signal_fence(__m); }
108
109 /// kill_dependency
110 template<typename _Tp>
111 inline _Tp
112 kill_dependency(_Tp __y) noexcept
113 {
114 _Tp __ret(__y);
115 return __ret;
116 }
117
118
119 // Base types for atomics.
120 template<typename _IntTp>
121 struct __atomic_base;
122
123 /// atomic_char
124 typedef __atomic_base<char> atomic_char;
125
126 /// atomic_schar
127 typedef __atomic_base<signed char> atomic_schar;
128
129 /// atomic_uchar
130 typedef __atomic_base<unsigned char> atomic_uchar;
131
132 /// atomic_short
133 typedef __atomic_base<short> atomic_short;
134
135 /// atomic_ushort
136 typedef __atomic_base<unsigned short> atomic_ushort;
137
138 /// atomic_int
139 typedef __atomic_base<int> atomic_int;
140
141 /// atomic_uint
142 typedef __atomic_base<unsigned int> atomic_uint;
143
144 /// atomic_long
145 typedef __atomic_base<long> atomic_long;
146
147 /// atomic_ulong
148 typedef __atomic_base<unsigned long> atomic_ulong;
149
150 /// atomic_llong
151 typedef __atomic_base<long long> atomic_llong;
152
153 /// atomic_ullong
154 typedef __atomic_base<unsigned long long> atomic_ullong;
155
156 /// atomic_wchar_t
157 typedef __atomic_base<wchar_t> atomic_wchar_t;
158
159 /// atomic_char16_t
160 typedef __atomic_base<char16_t> atomic_char16_t;
161
162 /// atomic_char32_t
163 typedef __atomic_base<char32_t> atomic_char32_t;
164
165 /// atomic_char32_t
166 typedef __atomic_base<char32_t> atomic_char32_t;
167
168
169 /// atomic_int_least8_t
170 typedef __atomic_base<int_least8_t> atomic_int_least8_t;
171
172 /// atomic_uint_least8_t
173 typedef __atomic_base<uint_least8_t> atomic_uint_least8_t;
174
175 /// atomic_int_least16_t
176 typedef __atomic_base<int_least16_t> atomic_int_least16_t;
177
178 /// atomic_uint_least16_t
179 typedef __atomic_base<uint_least16_t> atomic_uint_least16_t;
180
181 /// atomic_int_least32_t
182 typedef __atomic_base<int_least32_t> atomic_int_least32_t;
183
184 /// atomic_uint_least32_t
185 typedef __atomic_base<uint_least32_t> atomic_uint_least32_t;
186
187 /// atomic_int_least64_t
188 typedef __atomic_base<int_least64_t> atomic_int_least64_t;
189
190 /// atomic_uint_least64_t
191 typedef __atomic_base<uint_least64_t> atomic_uint_least64_t;
192
193
194 /// atomic_int_fast8_t
195 typedef __atomic_base<int_fast8_t> atomic_int_fast8_t;
196
197 /// atomic_uint_fast8_t
198 typedef __atomic_base<uint_fast8_t> atomic_uint_fast8_t;
199
200 /// atomic_int_fast16_t
201 typedef __atomic_base<int_fast16_t> atomic_int_fast16_t;
202
203 /// atomic_uint_fast16_t
204 typedef __atomic_base<uint_fast16_t> atomic_uint_fast16_t;
205
206 /// atomic_int_fast32_t
207 typedef __atomic_base<int_fast32_t> atomic_int_fast32_t;
208
209 /// atomic_uint_fast32_t
210 typedef __atomic_base<uint_fast32_t> atomic_uint_fast32_t;
211
212 /// atomic_int_fast64_t
213 typedef __atomic_base<int_fast64_t> atomic_int_fast64_t;
214
215 /// atomic_uint_fast64_t
216 typedef __atomic_base<uint_fast64_t> atomic_uint_fast64_t;
217
218
219 /// atomic_intptr_t
220 typedef __atomic_base<intptr_t> atomic_intptr_t;
221
222 /// atomic_uintptr_t
223 typedef __atomic_base<uintptr_t> atomic_uintptr_t;
224
225 /// atomic_size_t
226 typedef __atomic_base<size_t> atomic_size_t;
227
228 /// atomic_intmax_t
229 typedef __atomic_base<intmax_t> atomic_intmax_t;
230
231 /// atomic_uintmax_t
232 typedef __atomic_base<uintmax_t> atomic_uintmax_t;
233
234 /// atomic_ptrdiff_t
235 typedef __atomic_base<ptrdiff_t> atomic_ptrdiff_t;
236
237
238 #define ATOMIC_VAR_INIT(_VI) { _VI }
239
240 template<typename _Tp>
241 struct atomic;
242
243 template<typename _Tp>
244 struct atomic<_Tp*>;
245
246 /* The target's "set" value for test-and-set may not be exactly 1. */
247 #if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1
248 typedef bool __atomic_flag_data_type;
249 #else
250 typedef unsigned char __atomic_flag_data_type;
251 #endif
252
253 /**
254 * @brief Base type for atomic_flag.
255 *
256 * Base type is POD with data, allowing atomic_flag to derive from
257 * it and meet the standard layout type requirement. In addition to
258 * compatibility with a C interface, this allows different
259 * implementations of atomic_flag to use the same atomic operation
260 * functions, via a standard conversion to the __atomic_flag_base
261 * argument.
262 */
263 _GLIBCXX_BEGIN_EXTERN_C
264
265 struct __atomic_flag_base
266 {
267 __atomic_flag_data_type _M_i;
268 };
269
270 _GLIBCXX_END_EXTERN_C
271
272 #define ATOMIC_FLAG_INIT { 0 }
273
274 /// atomic_flag
275 struct atomic_flag : public __atomic_flag_base
276 {
277 atomic_flag() noexcept = default;
278 ~atomic_flag() noexcept = default;
279 atomic_flag(const atomic_flag&) = delete;
280 atomic_flag& operator=(const atomic_flag&) = delete;
281 atomic_flag& operator=(const atomic_flag&) volatile = delete;
282
283 // Conversion to ATOMIC_FLAG_INIT.
284 constexpr atomic_flag(bool __i) noexcept
285 : __atomic_flag_base{ _S_init(__i) }
286 { }
287
288 _GLIBCXX_ALWAYS_INLINE bool
289 test_and_set(memory_order __m = memory_order_seq_cst) noexcept
290 {
291 return __atomic_test_and_set (&_M_i, __m);
292 }
293
294 _GLIBCXX_ALWAYS_INLINE bool
295 test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept
296 {
297 return __atomic_test_and_set (&_M_i, __m);
298 }
299
300 _GLIBCXX_ALWAYS_INLINE void
301 clear(memory_order __m = memory_order_seq_cst) noexcept
302 {
303 memory_order __b = __m & __memory_order_mask;
304 __glibcxx_assert(__b != memory_order_consume);
305 __glibcxx_assert(__b != memory_order_acquire);
306 __glibcxx_assert(__b != memory_order_acq_rel);
307
308 __atomic_clear (&_M_i, __m);
309 }
310
311 _GLIBCXX_ALWAYS_INLINE void
312 clear(memory_order __m = memory_order_seq_cst) volatile noexcept
313 {
314 memory_order __b = __m & __memory_order_mask;
315 __glibcxx_assert(__b != memory_order_consume);
316 __glibcxx_assert(__b != memory_order_acquire);
317 __glibcxx_assert(__b != memory_order_acq_rel);
318
319 __atomic_clear (&_M_i, __m);
320 }
321
322 private:
323 static constexpr __atomic_flag_data_type
324 _S_init(bool __i)
325 { return __i ? __GCC_ATOMIC_TEST_AND_SET_TRUEVAL : 0; }
326 };
327
328
329 /// Base class for atomic integrals.
330 //
331 // For each of the integral types, define atomic_[integral type] struct
332 //
333 // atomic_bool bool
334 // atomic_char char
335 // atomic_schar signed char
336 // atomic_uchar unsigned char
337 // atomic_short short
338 // atomic_ushort unsigned short
339 // atomic_int int
340 // atomic_uint unsigned int
341 // atomic_long long
342 // atomic_ulong unsigned long
343 // atomic_llong long long
344 // atomic_ullong unsigned long long
345 // atomic_char16_t char16_t
346 // atomic_char32_t char32_t
347 // atomic_wchar_t wchar_t
348 //
349 // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or
350 // 8 bytes, since that is what GCC built-in functions for atomic
351 // memory access expect.
352 template<typename _ITp>
353 struct __atomic_base
354 {
355 private:
356 typedef _ITp __int_type;
357
358 __int_type _M_i;
359
360 public:
361 __atomic_base() noexcept = default;
362 ~__atomic_base() noexcept = default;
363 __atomic_base(const __atomic_base&) = delete;
364 __atomic_base& operator=(const __atomic_base&) = delete;
365 __atomic_base& operator=(const __atomic_base&) volatile = delete;
366
367 // Requires __int_type convertible to _M_i.
368 constexpr __atomic_base(__int_type __i) noexcept : _M_i (__i) { }
369
370 operator __int_type() const noexcept
371 { return load(); }
372
373 operator __int_type() const volatile noexcept
374 { return load(); }
375
376 __int_type
377 operator=(__int_type __i) noexcept
378 {
379 store(__i);
380 return __i;
381 }
382
383 __int_type
384 operator=(__int_type __i) volatile noexcept
385 {
386 store(__i);
387 return __i;
388 }
389
390 __int_type
391 operator++(int) noexcept
392 { return fetch_add(1); }
393
394 __int_type
395 operator++(int) volatile noexcept
396 { return fetch_add(1); }
397
398 __int_type
399 operator--(int) noexcept
400 { return fetch_sub(1); }
401
402 __int_type
403 operator--(int) volatile noexcept
404 { return fetch_sub(1); }
405
406 __int_type
407 operator++() noexcept
408 { return __atomic_add_fetch(&_M_i, 1, memory_order_seq_cst); }
409
410 __int_type
411 operator++() volatile noexcept
412 { return __atomic_add_fetch(&_M_i, 1, memory_order_seq_cst); }
413
414 __int_type
415 operator--() noexcept
416 { return __atomic_sub_fetch(&_M_i, 1, memory_order_seq_cst); }
417
418 __int_type
419 operator--() volatile noexcept
420 { return __atomic_sub_fetch(&_M_i, 1, memory_order_seq_cst); }
421
422 __int_type
423 operator+=(__int_type __i) noexcept
424 { return __atomic_add_fetch(&_M_i, __i, memory_order_seq_cst); }
425
426 __int_type
427 operator+=(__int_type __i) volatile noexcept
428 { return __atomic_add_fetch(&_M_i, __i, memory_order_seq_cst); }
429
430 __int_type
431 operator-=(__int_type __i) noexcept
432 { return __atomic_sub_fetch(&_M_i, __i, memory_order_seq_cst); }
433
434 __int_type
435 operator-=(__int_type __i) volatile noexcept
436 { return __atomic_sub_fetch(&_M_i, __i, memory_order_seq_cst); }
437
438 __int_type
439 operator&=(__int_type __i) noexcept
440 { return __atomic_and_fetch(&_M_i, __i, memory_order_seq_cst); }
441
442 __int_type
443 operator&=(__int_type __i) volatile noexcept
444 { return __atomic_and_fetch(&_M_i, __i, memory_order_seq_cst); }
445
446 __int_type
447 operator|=(__int_type __i) noexcept
448 { return __atomic_or_fetch(&_M_i, __i, memory_order_seq_cst); }
449
450 __int_type
451 operator|=(__int_type __i) volatile noexcept
452 { return __atomic_or_fetch(&_M_i, __i, memory_order_seq_cst); }
453
454 __int_type
455 operator^=(__int_type __i) noexcept
456 { return __atomic_xor_fetch(&_M_i, __i, memory_order_seq_cst); }
457
458 __int_type
459 operator^=(__int_type __i) volatile noexcept
460 { return __atomic_xor_fetch(&_M_i, __i, memory_order_seq_cst); }
461
462 bool
463 is_lock_free() const noexcept
464 { return __atomic_is_lock_free(sizeof(_M_i), nullptr); }
465
466 bool
467 is_lock_free() const volatile noexcept
468 { return __atomic_is_lock_free(sizeof(_M_i), nullptr); }
469
470 _GLIBCXX_ALWAYS_INLINE void
471 store(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept
472 {
473 memory_order __b = __m & __memory_order_mask;
474 __glibcxx_assert(__b != memory_order_acquire);
475 __glibcxx_assert(__b != memory_order_acq_rel);
476 __glibcxx_assert(__b != memory_order_consume);
477
478 __atomic_store_n(&_M_i, __i, __m);
479 }
480
481 _GLIBCXX_ALWAYS_INLINE void
482 store(__int_type __i,
483 memory_order __m = memory_order_seq_cst) volatile noexcept
484 {
485 memory_order __b = __m & __memory_order_mask;
486 __glibcxx_assert(__b != memory_order_acquire);
487 __glibcxx_assert(__b != memory_order_acq_rel);
488 __glibcxx_assert(__b != memory_order_consume);
489
490 __atomic_store_n(&_M_i, __i, __m);
491 }
492
493 _GLIBCXX_ALWAYS_INLINE __int_type
494 load(memory_order __m = memory_order_seq_cst) const noexcept
495 {
496 memory_order __b = __m & __memory_order_mask;
497 __glibcxx_assert(__b != memory_order_release);
498 __glibcxx_assert(__b != memory_order_acq_rel);
499
500 return __atomic_load_n(&_M_i, __m);
501 }
502
503 _GLIBCXX_ALWAYS_INLINE __int_type
504 load(memory_order __m = memory_order_seq_cst) const volatile noexcept
505 {
506 memory_order __b = __m & __memory_order_mask;
507 __glibcxx_assert(__b != memory_order_release);
508 __glibcxx_assert(__b != memory_order_acq_rel);
509
510 return __atomic_load_n(&_M_i, __m);
511 }
512
513 _GLIBCXX_ALWAYS_INLINE __int_type
514 exchange(__int_type __i,
515 memory_order __m = memory_order_seq_cst) noexcept
516 {
517 return __atomic_exchange_n(&_M_i, __i, __m);
518 }
519
520
521 _GLIBCXX_ALWAYS_INLINE __int_type
522 exchange(__int_type __i,
523 memory_order __m = memory_order_seq_cst) volatile noexcept
524 {
525 return __atomic_exchange_n(&_M_i, __i, __m);
526 }
527
528 _GLIBCXX_ALWAYS_INLINE bool
529 compare_exchange_weak(__int_type& __i1, __int_type __i2,
530 memory_order __m1, memory_order __m2) noexcept
531 {
532 memory_order __b2 = __m2 & __memory_order_mask;
533 memory_order __b1 = __m1 & __memory_order_mask;
534 __glibcxx_assert(__b2 != memory_order_release);
535 __glibcxx_assert(__b2 != memory_order_acq_rel);
536 __glibcxx_assert(__b2 <= __b1);
537
538 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, __m1, __m2);
539 }
540
541 _GLIBCXX_ALWAYS_INLINE bool
542 compare_exchange_weak(__int_type& __i1, __int_type __i2,
543 memory_order __m1,
544 memory_order __m2) volatile noexcept
545 {
546 memory_order __b2 = __m2 & __memory_order_mask;
547 memory_order __b1 = __m1 & __memory_order_mask;
548 __glibcxx_assert(__b2 != memory_order_release);
549 __glibcxx_assert(__b2 != memory_order_acq_rel);
550 __glibcxx_assert(__b2 <= __b1);
551
552 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, __m1, __m2);
553 }
554
555 _GLIBCXX_ALWAYS_INLINE bool
556 compare_exchange_weak(__int_type& __i1, __int_type __i2,
557 memory_order __m = memory_order_seq_cst) noexcept
558 {
559 return compare_exchange_weak(__i1, __i2, __m,
560 __cmpexch_failure_order(__m));
561 }
562
563 _GLIBCXX_ALWAYS_INLINE bool
564 compare_exchange_weak(__int_type& __i1, __int_type __i2,
565 memory_order __m = memory_order_seq_cst) volatile noexcept
566 {
567 return compare_exchange_weak(__i1, __i2, __m,
568 __cmpexch_failure_order(__m));
569 }
570
571 _GLIBCXX_ALWAYS_INLINE bool
572 compare_exchange_strong(__int_type& __i1, __int_type __i2,
573 memory_order __m1, memory_order __m2) noexcept
574 {
575 memory_order __b2 = __m2 & __memory_order_mask;
576 memory_order __b1 = __m1 & __memory_order_mask;
577 __glibcxx_assert(__b2 != memory_order_release);
578 __glibcxx_assert(__b2 != memory_order_acq_rel);
579 __glibcxx_assert(__b2 <= __b1);
580
581 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, __m1, __m2);
582 }
583
584 _GLIBCXX_ALWAYS_INLINE bool
585 compare_exchange_strong(__int_type& __i1, __int_type __i2,
586 memory_order __m1,
587 memory_order __m2) volatile noexcept
588 {
589 memory_order __b2 = __m2 & __memory_order_mask;
590 memory_order __b1 = __m1 & __memory_order_mask;
591
592 __glibcxx_assert(__b2 != memory_order_release);
593 __glibcxx_assert(__b2 != memory_order_acq_rel);
594 __glibcxx_assert(__b2 <= __b1);
595
596 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, __m1, __m2);
597 }
598
599 _GLIBCXX_ALWAYS_INLINE bool
600 compare_exchange_strong(__int_type& __i1, __int_type __i2,
601 memory_order __m = memory_order_seq_cst) noexcept
602 {
603 return compare_exchange_strong(__i1, __i2, __m,
604 __cmpexch_failure_order(__m));
605 }
606
607 _GLIBCXX_ALWAYS_INLINE bool
608 compare_exchange_strong(__int_type& __i1, __int_type __i2,
609 memory_order __m = memory_order_seq_cst) volatile noexcept
610 {
611 return compare_exchange_strong(__i1, __i2, __m,
612 __cmpexch_failure_order(__m));
613 }
614
615 _GLIBCXX_ALWAYS_INLINE __int_type
616 fetch_add(__int_type __i,
617 memory_order __m = memory_order_seq_cst) noexcept
618 { return __atomic_fetch_add(&_M_i, __i, __m); }
619
620 _GLIBCXX_ALWAYS_INLINE __int_type
621 fetch_add(__int_type __i,
622 memory_order __m = memory_order_seq_cst) volatile noexcept
623 { return __atomic_fetch_add(&_M_i, __i, __m); }
624
625 _GLIBCXX_ALWAYS_INLINE __int_type
626 fetch_sub(__int_type __i,
627 memory_order __m = memory_order_seq_cst) noexcept
628 { return __atomic_fetch_sub(&_M_i, __i, __m); }
629
630 _GLIBCXX_ALWAYS_INLINE __int_type
631 fetch_sub(__int_type __i,
632 memory_order __m = memory_order_seq_cst) volatile noexcept
633 { return __atomic_fetch_sub(&_M_i, __i, __m); }
634
635 _GLIBCXX_ALWAYS_INLINE __int_type
636 fetch_and(__int_type __i,
637 memory_order __m = memory_order_seq_cst) noexcept
638 { return __atomic_fetch_and(&_M_i, __i, __m); }
639
640 _GLIBCXX_ALWAYS_INLINE __int_type
641 fetch_and(__int_type __i,
642 memory_order __m = memory_order_seq_cst) volatile noexcept
643 { return __atomic_fetch_and(&_M_i, __i, __m); }
644
645 _GLIBCXX_ALWAYS_INLINE __int_type
646 fetch_or(__int_type __i,
647 memory_order __m = memory_order_seq_cst) noexcept
648 { return __atomic_fetch_or(&_M_i, __i, __m); }
649
650 _GLIBCXX_ALWAYS_INLINE __int_type
651 fetch_or(__int_type __i,
652 memory_order __m = memory_order_seq_cst) volatile noexcept
653 { return __atomic_fetch_or(&_M_i, __i, __m); }
654
655 _GLIBCXX_ALWAYS_INLINE __int_type
656 fetch_xor(__int_type __i,
657 memory_order __m = memory_order_seq_cst) noexcept
658 { return __atomic_fetch_xor(&_M_i, __i, __m); }
659
660 _GLIBCXX_ALWAYS_INLINE __int_type
661 fetch_xor(__int_type __i,
662 memory_order __m = memory_order_seq_cst) volatile noexcept
663 { return __atomic_fetch_xor(&_M_i, __i, __m); }
664 };
665
666
667 /// Partial specialization for pointer types.
668 template<typename _PTp>
669 struct __atomic_base<_PTp*>
670 {
671 private:
672 typedef _PTp* __pointer_type;
673
674 __pointer_type _M_p;
675
676 // Factored out to facilitate explicit specialization.
677 constexpr ptrdiff_t
678 _M_type_size(ptrdiff_t __d) const { return __d * sizeof(_PTp); }
679
680 constexpr ptrdiff_t
681 _M_type_size(ptrdiff_t __d) const volatile { return __d * sizeof(_PTp); }
682
683 public:
684 __atomic_base() noexcept = default;
685 ~__atomic_base() noexcept = default;
686 __atomic_base(const __atomic_base&) = delete;
687 __atomic_base& operator=(const __atomic_base&) = delete;
688 __atomic_base& operator=(const __atomic_base&) volatile = delete;
689
690 // Requires __pointer_type convertible to _M_p.
691 constexpr __atomic_base(__pointer_type __p) noexcept : _M_p (__p) { }
692
693 operator __pointer_type() const noexcept
694 { return load(); }
695
696 operator __pointer_type() const volatile noexcept
697 { return load(); }
698
699 __pointer_type
700 operator=(__pointer_type __p) noexcept
701 {
702 store(__p);
703 return __p;
704 }
705
706 __pointer_type
707 operator=(__pointer_type __p) volatile noexcept
708 {
709 store(__p);
710 return __p;
711 }
712
713 __pointer_type
714 operator++(int) noexcept
715 { return fetch_add(1); }
716
717 __pointer_type
718 operator++(int) volatile noexcept
719 { return fetch_add(1); }
720
721 __pointer_type
722 operator--(int) noexcept
723 { return fetch_sub(1); }
724
725 __pointer_type
726 operator--(int) volatile noexcept
727 { return fetch_sub(1); }
728
729 __pointer_type
730 operator++() noexcept
731 { return __atomic_add_fetch(&_M_p, _M_type_size(1),
732 memory_order_seq_cst); }
733
734 __pointer_type
735 operator++() volatile noexcept
736 { return __atomic_add_fetch(&_M_p, _M_type_size(1),
737 memory_order_seq_cst); }
738
739 __pointer_type
740 operator--() noexcept
741 { return __atomic_sub_fetch(&_M_p, _M_type_size(1),
742 memory_order_seq_cst); }
743
744 __pointer_type
745 operator--() volatile noexcept
746 { return __atomic_sub_fetch(&_M_p, _M_type_size(1),
747 memory_order_seq_cst); }
748
749 __pointer_type
750 operator+=(ptrdiff_t __d) noexcept
751 { return __atomic_add_fetch(&_M_p, _M_type_size(__d),
752 memory_order_seq_cst); }
753
754 __pointer_type
755 operator+=(ptrdiff_t __d) volatile noexcept
756 { return __atomic_add_fetch(&_M_p, _M_type_size(__d),
757 memory_order_seq_cst); }
758
759 __pointer_type
760 operator-=(ptrdiff_t __d) noexcept
761 { return __atomic_sub_fetch(&_M_p, _M_type_size(__d),
762 memory_order_seq_cst); }
763
764 __pointer_type
765 operator-=(ptrdiff_t __d) volatile noexcept
766 { return __atomic_sub_fetch(&_M_p, _M_type_size(__d),
767 memory_order_seq_cst); }
768
769 bool
770 is_lock_free() const noexcept
771 { return __atomic_is_lock_free(sizeof(__pointer_type), nullptr); }
772
773 bool
774 is_lock_free() const volatile noexcept
775 { return __atomic_is_lock_free(sizeof(__pointer_type), nullptr); }
776
777 _GLIBCXX_ALWAYS_INLINE void
778 store(__pointer_type __p,
779 memory_order __m = memory_order_seq_cst) noexcept
780 {
781 memory_order __b = __m & __memory_order_mask;
782
783 __glibcxx_assert(__b != memory_order_acquire);
784 __glibcxx_assert(__b != memory_order_acq_rel);
785 __glibcxx_assert(__b != memory_order_consume);
786
787 __atomic_store_n(&_M_p, __p, __m);
788 }
789
790 _GLIBCXX_ALWAYS_INLINE void
791 store(__pointer_type __p,
792 memory_order __m = memory_order_seq_cst) volatile noexcept
793 {
794 memory_order __b = __m & __memory_order_mask;
795 __glibcxx_assert(__b != memory_order_acquire);
796 __glibcxx_assert(__b != memory_order_acq_rel);
797 __glibcxx_assert(__b != memory_order_consume);
798
799 __atomic_store_n(&_M_p, __p, __m);
800 }
801
802 _GLIBCXX_ALWAYS_INLINE __pointer_type
803 load(memory_order __m = memory_order_seq_cst) const noexcept
804 {
805 memory_order __b = __m & __memory_order_mask;
806 __glibcxx_assert(__b != memory_order_release);
807 __glibcxx_assert(__b != memory_order_acq_rel);
808
809 return __atomic_load_n(&_M_p, __m);
810 }
811
812 _GLIBCXX_ALWAYS_INLINE __pointer_type
813 load(memory_order __m = memory_order_seq_cst) const volatile noexcept
814 {
815 memory_order __b = __m & __memory_order_mask;
816 __glibcxx_assert(__b != memory_order_release);
817 __glibcxx_assert(__b != memory_order_acq_rel);
818
819 return __atomic_load_n(&_M_p, __m);
820 }
821
822 _GLIBCXX_ALWAYS_INLINE __pointer_type
823 exchange(__pointer_type __p,
824 memory_order __m = memory_order_seq_cst) noexcept
825 {
826 return __atomic_exchange_n(&_M_p, __p, __m);
827 }
828
829
830 _GLIBCXX_ALWAYS_INLINE __pointer_type
831 exchange(__pointer_type __p,
832 memory_order __m = memory_order_seq_cst) volatile noexcept
833 {
834 return __atomic_exchange_n(&_M_p, __p, __m);
835 }
836
837 _GLIBCXX_ALWAYS_INLINE bool
838 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
839 memory_order __m1,
840 memory_order __m2) noexcept
841 {
842 memory_order __b2 = __m2 & __memory_order_mask;
843 memory_order __b1 = __m1 & __memory_order_mask;
844 __glibcxx_assert(__b2 != memory_order_release);
845 __glibcxx_assert(__b2 != memory_order_acq_rel);
846 __glibcxx_assert(__b2 <= __b1);
847
848 return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, __m1, __m2);
849 }
850
851 _GLIBCXX_ALWAYS_INLINE bool
852 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
853 memory_order __m1,
854 memory_order __m2) volatile noexcept
855 {
856 memory_order __b2 = __m2 & __memory_order_mask;
857 memory_order __b1 = __m1 & __memory_order_mask;
858
859 __glibcxx_assert(__b2 != memory_order_release);
860 __glibcxx_assert(__b2 != memory_order_acq_rel);
861 __glibcxx_assert(__b2 <= __b1);
862
863 return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, __m1, __m2);
864 }
865
866 _GLIBCXX_ALWAYS_INLINE __pointer_type
867 fetch_add(ptrdiff_t __d,
868 memory_order __m = memory_order_seq_cst) noexcept
869 { return __atomic_fetch_add(&_M_p, _M_type_size(__d), __m); }
870
871 _GLIBCXX_ALWAYS_INLINE __pointer_type
872 fetch_add(ptrdiff_t __d,
873 memory_order __m = memory_order_seq_cst) volatile noexcept
874 { return __atomic_fetch_add(&_M_p, _M_type_size(__d), __m); }
875
876 _GLIBCXX_ALWAYS_INLINE __pointer_type
877 fetch_sub(ptrdiff_t __d,
878 memory_order __m = memory_order_seq_cst) noexcept
879 { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), __m); }
880
881 _GLIBCXX_ALWAYS_INLINE __pointer_type
882 fetch_sub(ptrdiff_t __d,
883 memory_order __m = memory_order_seq_cst) volatile noexcept
884 { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), __m); }
885 };
886
887 // @} group atomics
888
889 _GLIBCXX_END_NAMESPACE_VERSION
890 } // namespace std
891
892 #endif
893