OSDN Git Service

2008-04-10 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / c_compatibility / stdatomic.h
1 // -*- C++ -*- compatibility header.
2
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.
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 // 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.
20
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.
29
30 /** @file stdatomic.h
31  *  This is a Standard C++ Library header.
32  */
33
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
37
38 #ifndef _GLIBCXX_STDATOMIC_H
39 #define _GLIBCXX_STDATOMIC_H 1
40
41 _GLIBCXX_BEGIN_NAMESPACE(std)
42 _GLIBCXX_BEGIN_EXTERN_C
43
44   /// Enumeration for memory_order
45   typedef enum memory_order 
46     {
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;
53
54
55   // Base for atomic_flag.
56   struct __atomic_flag_base
57   {
58     bool _M_b;
59   };
60
61   // Base for atomic_address
62   struct __atomic_address_base
63   {
64     void* _M_i;
65   };
66
67   // POD base classes for atomic intgral types.
68   struct __atomic_bool_base
69   {
70     bool _M_i;
71   };
72
73   struct __atomic_char_base
74   {
75     char _M_i;
76   };
77
78   struct __atomic_schar_base
79   {
80     signed char _M_i;
81   };
82
83   struct __atomic_uchar_base
84   {
85     unsigned char _M_i;
86   };
87
88   struct __atomic_short_base
89   {
90     short _M_i;
91   };
92
93   struct __atomic_ushort_base
94   {
95     unsigned short _M_i;
96   };
97
98   struct __atomic_int_base
99   {
100     int _M_i;
101   };
102
103   struct __atomic_uint_base
104   {
105     unsigned int _M_i;
106   };
107
108   struct __atomic_long_base
109   {
110     long _M_i;
111   };
112
113   struct __atomic_ulong_base
114   {
115     unsigned long _M_i;
116   };
117
118   struct __atomic_llong_base
119   {
120     long long _M_i;
121   };
122
123   struct __atomic_ullong_base
124   {
125     unsigned long long _M_i;
126   };
127
128   struct __atomic_wchar_t_base
129   {
130     wchar_t _M_i;
131   };
132
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
138
139 #define ATOMIC_FLAG_INIT { { false } }
140 #define _ATOMIC_MEMBER_ ((__a)->_M_base._M_i)
141
142 extern "C++"
143 {
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;
161 }
162 #else
163
164 #define ATOMIC_FLAG_INIT { false }
165 #define _ATOMIC_MEMBER_ ((__a)->_M_i)
166
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;
182
183 #define atomic_is_lock_free(__a)                                \
184   false
185
186 #define atomic_load(__a)                                        \
187   _ATOMIC_LOAD_(__a, memory_order_seq_cst)
188
189 #define atomic_load_explicit(__a, __x)                          \
190   _ATOMIC_LOAD_(__a, __x)
191
192 #define atomic_store(__a, __m)                                  \
193   _ATOMIC_STORE_(__a, __m, memory_order_seq_cst)
194
195 #define atomic_store_explicit(__a, __m, __x)                    \
196   _ATOMIC_STORE_(__a, __m, __x)
197
198 #define atomic_swap(__a, __m)                                   \
199   _ATOMIC_MODIFY_(__a, =, __m, memory_order_seq_cst)
200
201 #define atomic_swap_explicit(__a, __m, __x)                     \
202   _ATOMIC_MODIFY_(__a, =, __m, __x)
203
204 #define atomic_compare_swap(__a, __e, __m)                      \
205   _ATOMIC_CMPSWP_(__a, __e, __m, memory_order_seq_cst)
206
207 #define atomic_compare_swap_explicit(__a, __e, __m, __x, __y)   \
208   _ATOMIC_CMPSWP_(__a, __e, __m, __x)
209
210 #define atomic_fence(__a, __x)                                  \
211   ({ _ATOMIC_FENCE_(__a, __x); })
212
213 #define atomic_fetch_add_explicit(__a, __m, __x)                \
214   _ATOMIC_MODIFY_(__a, +=, __m, __x)
215
216 #define atomic_fetch_add(__a, __m)                              \
217   _ATOMIC_MODIFY_(__a, +=, __m, memory_order_seq_cst)
218
219 #define atomic_fetch_sub_explicit(__a, __m, __x)                \
220   _ATOMIC_MODIFY_(__a, -=, __m, __x)
221
222 #define atomic_fetch_sub(__a, __m)                              \
223   _ATOMIC_MODIFY_(__a, -=, __m, memory_order_seq_cst)
224
225 #define atomic_fetch_and_explicit(__a, __m, __x)                \
226   _ATOMIC_MODIFY_(__a, &=, __m, __x)
227
228 #define atomic_fetch_and(__a, __m)                              \
229   _ATOMIC_MODIFY_(__a, &=, __m, memory_order_seq_cst)
230
231 #define atomic_fetch_or_explicit(__a, __m, __x)                 \
232   _ATOMIC_MODIFY_(__a, |=, __m, __x)
233
234 #define atomic_fetch_or(__a, __m)                               \
235   _ATOMIC_MODIFY_(__a, |=, __m, memory_order_seq_cst)
236
237 #define atomic_fetch_xor_explicit(__a, __m, __x)                \
238   _ATOMIC_MODIFY_(__a, ^=, __m, __x)
239
240 #define atomic_fetch_xor(__a, __m)                              \
241   _ATOMIC_MODIFY_(__a, ^=, __m, memory_order_seq_cst)
242
243 #endif
244   
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;
254
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;
263
264   typedef atomic_long           atomic_intptr_t;
265   typedef atomic_ulong          atomic_uintptr_t;
266
267   typedef atomic_long           atomic_ssize_t;
268   typedef atomic_ulong          atomic_size_t;
269
270   typedef atomic_llong          atomic_intmax_t;
271   typedef atomic_ullong         atomic_uintmax_t;
272
273   typedef atomic_long           atomic_ptrdiff_t;
274
275   typedef atomic_int_least16_t  atomic_char16_t;
276   typedef atomic_int_least32_t  atomic_char32_t;
277
278   // Accessor functions for atomic_flag.
279   extern bool 
280   atomic_flag_test_and_set(volatile atomic_flag*);
281   
282   extern bool 
283   atomic_flag_test_and_set_explicit(volatile atomic_flag*, memory_order);
284   
285   extern void 
286   atomic_flag_clear(volatile atomic_flag*);
287   
288   extern void 
289   atomic_flag_clear_explicit(volatile atomic_flag*, memory_order);
290   
291   extern void 
292   atomic_flag_fence(const volatile atomic_flag*, memory_order);
293   
294   extern void 
295   __atomic_flag_wait_explicit(volatile atomic_flag*, memory_order);
296   
297   extern volatile atomic_flag* 
298   __atomic_flag_for_address(const volatile void* __z) __attribute__((const));
299    
300   // External object.
301   extern const atomic_flag atomic_global_fence_compatibility;
302   
303   /// 29.2 Lock-free Property
304 #define ATOMIC_INTEGRAL_LOCK_FREE 0
305 #define ATOMIC_ADDRESS_LOCK_FREE 0
306
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; })
315
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; })
324
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; })
334
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; })
347
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);                                        \
352   })
353
354 _GLIBCXX_END_EXTERN_C
355 _GLIBCXX_END_NAMESPACE
356
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;
365
366 using std::atomic_flag;
367
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;
381
382 using std::atomic_address;
383 using std::atomic;
384
385 #endif
386
387 #endif