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