1 // -*- C++ -*- compatibility header.
3 // Copyright (C) 2008 Free Software Foundation, Inc.
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 2, or (at your option)
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.
16 // You should have received a copy of the GNU General Public License
17 // along with this library; see the file COPYING. If not, write to
18 // the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19 // Boston, MA 02110-1301, USA.
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
31 * This is a Standard C++ Library header.
34 #include <bits/c++config.h>
36 #include <stdbool.h> // XXX need to define bool w/o stdbool.h in tr1/cstdbool
38 #ifndef _GLIBCXX_STDATOMIC_H
39 #define _GLIBCXX_STDATOMIC_H 1
41 _GLIBCXX_BEGIN_NAMESPACE(std
)
42 _GLIBCXX_BEGIN_EXTERN_C
44 /// Enumeration for memory_order
45 typedef enum memory_order
55 // Base for atomic_flag.
56 struct __atomic_flag_base
61 // Base for atomic_address
62 struct __atomic_address_base
67 // POD base classes for atomic intgral types.
68 struct __atomic_bool_base
73 struct __atomic_char_base
78 struct __atomic_schar_base
83 struct __atomic_uchar_base
88 struct __atomic_short_base
93 struct __atomic_ushort_base
98 struct __atomic_int_base
103 struct __atomic_uint_base
108 struct __atomic_long_base
113 struct __atomic_ulong_base
118 struct __atomic_llong_base
123 struct __atomic_ullong_base
125 unsigned long long _M_i
;
128 struct __atomic_wchar_t_base
133 // Switch atomic integral base types based on C or C++. In
134 // addition, for "C" only provide type-generic macros for atomic
135 // operations. (As C++ accomplishes the same thing with sets of
136 // overloaded functions.
139 #define ATOMIC_FLAG_INIT { { false } }
140 #define _ATOMIC_MEMBER_ ((__a)->_M_base._M_i)
145 struct atomic_address
;
151 struct atomic_ushort
;
157 struct atomic_ullong
;
158 struct atomic_wchar_t
;
159 template<typename _Tp
>
164 #define ATOMIC_FLAG_INIT { false }
165 #define _ATOMIC_MEMBER_ ((__a)->_M_i)
167 typedef struct __atomic_flag_base atomic_flag
;
168 typedef struct __atomic_address_base atomic_address
;
169 typedef struct __atomic_bool_base atomic_bool
;
170 typedef struct __atomic_char_base atomic_char
;
171 typedef struct __atomic_schar_base atomic_schar
;
172 typedef struct __atomic_uchar_base atomic_uchar
;
173 typedef struct __atomic_short_base atomic_short
;
174 typedef struct __atomic_ushort_base atomic_ushort
;
175 typedef struct __atomic_int_base atomic_int
;
176 typedef struct __atomic_uint_base atomic_uint
;
177 typedef struct __atomic_long_base atomic_long
;
178 typedef struct __atomic_ulong_base atomic_ulong
;
179 typedef struct __atomic_llong_base atomic_llong
;
180 typedef struct __atomic_ullong_base atomic_ullong
;
181 typedef struct __atomic_wchar_t_base atomic_wchar_t
;
183 #define atomic_is_lock_free(__a) \
186 #define atomic_load(__a) \
187 _ATOMIC_LOAD_(__a, memory_order_seq_cst)
189 #define atomic_load_explicit(__a, __x) \
190 _ATOMIC_LOAD_(__a, __x)
192 #define atomic_store(__a, __m) \
193 _ATOMIC_STORE_(__a, __m, memory_order_seq_cst)
195 #define atomic_store_explicit(__a, __m, __x) \
196 _ATOMIC_STORE_(__a, __m, __x)
198 #define atomic_swap(__a, __m) \
199 _ATOMIC_MODIFY_(__a, =, __m, memory_order_seq_cst)
201 #define atomic_swap_explicit(__a, __m, __x) \
202 _ATOMIC_MODIFY_(__a, =, __m, __x)
204 #define atomic_compare_swap(__a, __e, __m) \
205 _ATOMIC_CMPSWP_(__a, __e, __m, memory_order_seq_cst)
207 #define atomic_compare_swap_explicit(__a, __e, __m, __x, __y) \
208 _ATOMIC_CMPSWP_(__a, __e, __m, __x)
210 #define atomic_fence(__a, __x) \
211 ({ _ATOMIC_FENCE_(__a, __x); })
213 #define atomic_fetch_add_explicit(__a, __m, __x) \
214 _ATOMIC_MODIFY_(__a, +=, __m, __x)
216 #define atomic_fetch_add(__a, __m) \
217 _ATOMIC_MODIFY_(__a, +=, __m, memory_order_seq_cst)
219 #define atomic_fetch_sub_explicit(__a, __m, __x) \
220 _ATOMIC_MODIFY_(__a, -=, __m, __x)
222 #define atomic_fetch_sub(__a, __m) \
223 _ATOMIC_MODIFY_(__a, -=, __m, memory_order_seq_cst)
225 #define atomic_fetch_and_explicit(__a, __m, __x) \
226 _ATOMIC_MODIFY_(__a, &=, __m, __x)
228 #define atomic_fetch_and(__a, __m) \
229 _ATOMIC_MODIFY_(__a, &=, __m, memory_order_seq_cst)
231 #define atomic_fetch_or_explicit(__a, __m, __x) \
232 _ATOMIC_MODIFY_(__a, |=, __m, __x)
234 #define atomic_fetch_or(__a, __m) \
235 _ATOMIC_MODIFY_(__a, |=, __m, memory_order_seq_cst)
237 #define atomic_fetch_xor_explicit(__a, __m, __x) \
238 _ATOMIC_MODIFY_(__a, ^=, __m, __x)
240 #define atomic_fetch_xor(__a, __m) \
241 _ATOMIC_MODIFY_(__a, ^=, __m, memory_order_seq_cst)
245 // Typedefs for other atomic integral types.
246 typedef atomic_schar atomic_int_least8_t
;
247 typedef atomic_uchar atomic_uint_least8_t
;
248 typedef atomic_short atomic_int_least16_t
;
249 typedef atomic_ushort atomic_uint_least16_t
;
250 typedef atomic_int atomic_int_least32_t
;
251 typedef atomic_uint atomic_uint_least32_t
;
252 typedef atomic_llong atomic_int_least64_t
;
253 typedef atomic_ullong atomic_uint_least64_t
;
255 typedef atomic_schar atomic_int_fast8_t
;
256 typedef atomic_uchar atomic_uint_fast8_t
;
257 typedef atomic_short atomic_int_fast16_t
;
258 typedef atomic_ushort atomic_uint_fast16_t
;
259 typedef atomic_int atomic_int_fast32_t
;
260 typedef atomic_uint atomic_uint_fast32_t
;
261 typedef atomic_llong atomic_int_fast64_t
;
262 typedef atomic_ullong atomic_uint_fast64_t
;
264 typedef atomic_long atomic_intptr_t
;
265 typedef atomic_ulong atomic_uintptr_t
;
267 typedef atomic_long atomic_ssize_t
;
268 typedef atomic_ulong atomic_size_t
;
270 typedef atomic_llong atomic_intmax_t
;
271 typedef atomic_ullong atomic_uintmax_t
;
273 typedef atomic_long atomic_ptrdiff_t
;
275 typedef atomic_int_least16_t atomic_char16_t
;
276 typedef atomic_int_least32_t atomic_char32_t
;
278 // Accessor functions for atomic_flag.
280 atomic_flag_test_and_set(volatile atomic_flag
*);
283 atomic_flag_test_and_set_explicit(volatile atomic_flag
*, memory_order
);
286 atomic_flag_clear(volatile atomic_flag
*);
289 atomic_flag_clear_explicit(volatile atomic_flag
*, memory_order
);
292 atomic_flag_fence(const volatile atomic_flag
*, memory_order
);
295 __atomic_flag_wait_explicit(volatile atomic_flag
*, memory_order
);
297 extern volatile atomic_flag
*
298 __atomic_flag_for_address(const volatile void* __z
) __attribute__((const));
301 extern const atomic_flag atomic_global_fence_compatibility
;
303 /// 29.2 Lock-free Property
304 #define ATOMIC_INTEGRAL_LOCK_FREE 0
305 #define ATOMIC_ADDRESS_LOCK_FREE 0
307 // Implementation specific defines.
308 #define _ATOMIC_LOAD_(__a, __x) \
309 ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \
310 volatile atomic_flag* __g = __atomic_flag_for_address(__p); \
311 __atomic_flag_wait_explicit(__g, __x); \
312 __typeof__ _ATOMIC_MEMBER_ __r = *__p; \
313 atomic_flag_clear_explicit(__g, __x); \
316 #define _ATOMIC_STORE_(__a, __m, __x) \
317 ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \
318 __typeof__(__m) __v = (__m); \
319 volatile atomic_flag* __g = __atomic_flag_for_address(__p); \
320 __atomic_flag_wait_explicit(__g, __x); \
322 atomic_flag_clear_explicit(__g, __x); \
325 #define _ATOMIC_MODIFY_(__a, __o, __m, __x) \
326 ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \
327 __typeof__(__m) __v = (__m); \
328 volatile atomic_flag* __g = __atomic_flag_for_address(__p); \
329 __atomic_flag_wait_explicit(__g, __x); \
330 __typeof__ _ATOMIC_MEMBER_ __r = *__p; \
332 atomic_flag_clear_explicit(__g, __x); \
335 #define _ATOMIC_CMPSWP_(__a, __e, __m, __x) \
336 ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \
337 __typeof__(__e) __q = (__e); \
338 __typeof__(__m) __v = (__m); \
340 volatile atomic_flag* __g = __atomic_flag_for_address(__p); \
341 __atomic_flag_wait_explicit(__g, __x); \
342 __typeof__ _ATOMIC_MEMBER_ __t__ = *__p; \
343 if (__t__ == *__q) { *__p = __v; __r = true; } \
344 else { *__q = __t__; __r = false; } \
345 atomic_flag_clear_explicit(__g, __x); \
348 #define _ATOMIC_FENCE_(__a, __x) \
349 ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_; \
350 volatile atomic_flag* __g = __atomic_flag_for_address(__p); \
351 atomic_flag_fence(__g, __x); \
354 _GLIBCXX_END_EXTERN_C
355 _GLIBCXX_END_NAMESPACE
358 // Inject into global namespace iff C++.
359 using std::memory_order
;
360 using std::memory_order_relaxed
;
361 using std::memory_order_acquire
;
362 using std::memory_order_release
;
363 using std::memory_order_acq_rel
;
364 using std::memory_order_seq_cst
;
366 using std::atomic_flag
;
368 using std::atomic_bool
;
369 using std::atomic_char
;
370 using std::atomic_schar
;
371 using std::atomic_uchar
;
372 using std::atomic_short
;
373 using std::atomic_ushort
;
374 using std::atomic_int
;
375 using std::atomic_uint
;
376 using std::atomic_long
;
377 using std::atomic_ulong
;
378 using std::atomic_llong
;
379 using std::atomic_ullong
;
380 using std::atomic_wchar_t
;
382 using std::atomic_address
;