1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
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 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
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 | operator&(memory_order __m, __memory_order_modifier __mod) |
81 | { |
82 | return memory_order(__m & int(__mod)); |
83 | } |
84 | |
85 | |
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 | |
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 | |
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 | |
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 | |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | |
146 | |
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 | |
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 | |
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 | |
215 | |
216 | |
217 | |
218 | |
219 | |
220 | |
221 | |
222 | |
223 | |
224 | |
225 | |
226 | |
227 | |
228 | |
229 | |
230 | |
231 | |
232 | |
233 | |
234 | |
235 | |
236 | |
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 | |
256 | 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 | operator++() noexcept |
296 | { 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 | operator--() noexcept |
304 | { 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 | |
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 | |
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 | memory_order __b = __m & __memory_order_mask; |
393 | __glibcxx_assert(__b != memory_order_release); |
394 | __glibcxx_assert(__b != memory_order_acq_rel); |
395 | |
396 | 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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
792 | |
793 | _GLIBCXX_END_NAMESPACE_VERSION |
794 | } |
795 | |
796 | #endif |
797 | |