2008-05-30 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / libstdc++-v3 / include / c_compatibility / stdatomic.h
blobe5f7dcfe6c120e4caac2f7c07362fd359a387d37
1 // -*- C++ -*- compatibility header.
3 // Copyright (C) 2008 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 2, or (at your option)
9 // any later version.
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.
30 /** @file stdatomic.h
31 * This is a Standard C++ Library header.
34 #include <bits/c++config.h>
35 #include <stddef.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
47 memory_order_relaxed,
48 memory_order_acquire,
49 memory_order_release,
50 memory_order_acq_rel,
51 memory_order_seq_cst
52 } memory_order;
55 // Base for atomic_flag.
56 struct __atomic_flag_base
58 bool _M_b;
61 // Base for atomic_address
62 struct __atomic_address_base
64 void* _M_i;
67 // POD base classes for atomic intgral types.
68 struct __atomic_bool_base
70 bool _M_i;
73 struct __atomic_char_base
75 char _M_i;
78 struct __atomic_schar_base
80 signed char _M_i;
83 struct __atomic_uchar_base
85 unsigned char _M_i;
88 struct __atomic_short_base
90 short _M_i;
93 struct __atomic_ushort_base
95 unsigned short _M_i;
98 struct __atomic_int_base
100 int _M_i;
103 struct __atomic_uint_base
105 unsigned int _M_i;
108 struct __atomic_long_base
110 long _M_i;
113 struct __atomic_ulong_base
115 unsigned long _M_i;
118 struct __atomic_llong_base
120 long long _M_i;
123 struct __atomic_ullong_base
125 unsigned long long _M_i;
128 struct __atomic_wchar_t_base
130 wchar_t _M_i;
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.
137 #ifdef __cplusplus
139 #define ATOMIC_FLAG_INIT { { false } }
140 #define _ATOMIC_MEMBER_ ((__a)->_M_base._M_i)
142 extern "C++"
144 struct atomic_flag;
145 struct atomic_address;
146 struct atomic_bool;
147 struct atomic_char;
148 struct atomic_schar;
149 struct atomic_uchar;
150 struct atomic_short;
151 struct atomic_ushort;
152 struct atomic_int;
153 struct atomic_uint;
154 struct atomic_long;
155 struct atomic_ulong;
156 struct atomic_llong;
157 struct atomic_ullong;
158 struct atomic_wchar_t;
159 template<typename _Tp>
160 struct atomic;
162 #else
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) \
184 false
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)
243 #endif
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.
279 extern bool
280 atomic_flag_test_and_set(volatile atomic_flag*);
282 extern bool
283 atomic_flag_test_and_set_explicit(volatile atomic_flag*, memory_order);
285 extern void
286 atomic_flag_clear(volatile atomic_flag*);
288 extern void
289 atomic_flag_clear_explicit(volatile atomic_flag*, memory_order);
291 extern void
292 atomic_flag_fence(const volatile atomic_flag*, memory_order);
294 extern void
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));
300 // External object.
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); \
314 __r; })
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); \
321 *__p = __v; \
322 atomic_flag_clear_explicit(__g, __x); \
323 __v; })
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; \
331 *__p __o __v; \
332 atomic_flag_clear_explicit(__g, __x); \
333 __r; })
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); \
339 bool __r; \
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); \
346 __r; })
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
357 #ifdef __cplusplus
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;
383 using std::atomic;
385 #endif
387 #endif