OSDN Git Service

2009-10-15 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / atomic_0.h
1 // -*- C++ -*- header.
2
3 // Copyright (C) 2008, 2009
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
20
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24 // <http://www.gnu.org/licenses/>.
25
26 /** @file bits/atomic_0.h
27  *  This is an internal header file, included by other library headers.
28  *  You should not attempt to use it directly.
29  */
30
31 #ifndef _GLIBCXX_ATOMIC_0_H
32 #define _GLIBCXX_ATOMIC_0_H 1
33
34 #pragma GCC system_header
35
36 // _GLIBCXX_BEGIN_NAMESPACE(std)
37
38   // 0 == __atomic0 == Never lock-free
39 namespace __atomic0
40 {
41   struct atomic_flag;
42
43   // Implementation specific defines.
44 #define _ATOMIC_LOAD_(__a, __x)                                            \
45   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;          \
46     volatile __atomic_flag_base* __g = __atomic_flag_for_address(__p);     \
47     __atomic_flag_wait_explicit(__g, __x);                                 \
48     __typeof__ _ATOMIC_MEMBER_ __r = *__p;                                 \
49     atomic_flag_clear_explicit(__g, __x);                                  \
50     __r; })
51
52 #define _ATOMIC_STORE_(__a, __m, __x)                                      \
53   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;          \
54     __typeof__(__m) __v = (__m);                                           \
55     volatile __atomic_flag_base* __g = __atomic_flag_for_address(__p);     \
56     __atomic_flag_wait_explicit(__g, __x);                                 \
57     *__p = __v;                                                            \
58     atomic_flag_clear_explicit(__g, __x);                                  \
59     __v; })
60
61 #define _ATOMIC_MODIFY_(__a, __o, __m, __x)                                \
62   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;          \
63     __typeof__(__m) __v = (__m);                                           \
64     volatile __atomic_flag_base* __g = __atomic_flag_for_address(__p);     \
65     __atomic_flag_wait_explicit(__g, __x);                                 \
66     __typeof__ _ATOMIC_MEMBER_ __r = *__p;                                 \
67     *__p __o __v;                                                          \
68     atomic_flag_clear_explicit(__g, __x);                                  \
69     __r; })
70
71 #define _ATOMIC_CMPEXCHNG_(__a, __e, __m, __x)                             \
72   ({ volatile __typeof__ _ATOMIC_MEMBER_* __p = &_ATOMIC_MEMBER_;          \
73     __typeof__(__e) __q = (__e);                                           \
74     __typeof__(__m) __v = (__m);                                           \
75     bool __r;                                                              \
76     volatile __atomic_flag_base* __g = __atomic_flag_for_address(__p);     \
77     __atomic_flag_wait_explicit(__g, __x);                                 \
78     __typeof__ _ATOMIC_MEMBER_ __t__ = *__p;                               \
79     if (__t__ == *__q) { *__p = __v; __r = true; }                         \
80     else { *__q = __t__; __r = false; }                                    \
81     atomic_flag_clear_explicit(__g, __x);                                  \
82     __r; })
83
84   /// atomic_flag
85   struct atomic_flag : public __atomic_flag_base
86   {
87     atomic_flag() = default;
88     ~atomic_flag() = default;
89     atomic_flag(const atomic_flag&) = delete;
90     atomic_flag& operator=(const atomic_flag&) = delete;
91
92     // Conversion to ATOMIC_FLAG_INIT.
93     atomic_flag(bool __i): __atomic_flag_base({ __i }) { }
94
95     bool
96     test_and_set(memory_order __m = memory_order_seq_cst) volatile;
97
98     void
99     clear(memory_order __m = memory_order_seq_cst) volatile;
100   };
101
102   /// 29.4.2, address types
103   struct atomic_address
104   {
105   private:
106     void* _M_i;
107
108   public:
109     atomic_address() = default;
110     ~atomic_address() = default;
111     atomic_address(const atomic_address&) = delete;
112     atomic_address& operator=(const atomic_address&) = delete;
113
114     atomic_address(void* __v) { _M_i = __v; }
115
116     bool
117     is_lock_free() const volatile
118     { return false; }
119
120     void
121     store(void* __v, memory_order __m = memory_order_seq_cst) volatile
122     {
123       __glibcxx_assert(__m != memory_order_acquire);
124       __glibcxx_assert(__m != memory_order_acq_rel);
125       __glibcxx_assert(__m != memory_order_consume);
126       _ATOMIC_STORE_(this, __v, __m);
127     }
128
129     void*
130     load(memory_order __m = memory_order_seq_cst) const volatile
131     {
132       __glibcxx_assert(__m != memory_order_release);
133       __glibcxx_assert(__m != memory_order_acq_rel);
134       return _ATOMIC_LOAD_(this, __m);
135     }
136
137     void*
138     exchange(void* __v, memory_order __m = memory_order_seq_cst) volatile
139     { return _ATOMIC_MODIFY_(this, =, __v, __m); }
140
141     bool
142     compare_exchange_weak(void*& __v1, void* __v2, memory_order __m1,
143                           memory_order __m2) volatile
144     {
145       __glibcxx_assert(__m2 != memory_order_release);
146       __glibcxx_assert(__m2 != memory_order_acq_rel);
147       __glibcxx_assert(__m2 <= __m1);
148       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
149     }
150
151     bool
152     compare_exchange_weak(void*& __v1, void* __v2,
153                           memory_order __m = memory_order_seq_cst) volatile
154     {
155       return compare_exchange_weak(__v1, __v2, __m,
156                                    __calculate_memory_order(__m));
157     }
158
159     bool
160     compare_exchange_strong(void*& __v1, void* __v2, memory_order __m1,
161                             memory_order __m2) volatile
162     {
163       __glibcxx_assert(__m2 != memory_order_release);
164       __glibcxx_assert(__m2 != memory_order_acq_rel);
165       __glibcxx_assert(__m2 <= __m1);
166       return _ATOMIC_CMPEXCHNG_(this, &__v1, __v2, __m1);
167     }
168
169     bool
170     compare_exchange_strong(void*& __v1, void* __v2,
171                           memory_order __m = memory_order_seq_cst) volatile
172     {
173       return compare_exchange_strong(__v1, __v2, __m,
174                                      __calculate_memory_order(__m));
175     }
176
177     void*
178     fetch_add(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile
179     {
180       void* volatile* __p = &(_M_i);
181       volatile __atomic_flag_base* __g = __atomic_flag_for_address(__p);
182       __atomic_flag_wait_explicit(__g, __m);
183       void* __r = *__p;
184       *__p = (void*)((char*)(*__p) + __d);
185       atomic_flag_clear_explicit(__g, __m);
186       return __r;
187     }
188
189     void*
190     fetch_sub(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile
191     {
192       void* volatile* __p = &(_M_i);
193       volatile __atomic_flag_base* __g = __atomic_flag_for_address(__p);
194       __atomic_flag_wait_explicit(__g, __m);
195       void* __r = *__p;
196       *__p = (void*)((char*)(*__p) - __d);
197       atomic_flag_clear_explicit(__g, __m);
198       return __r;
199     }
200
201     operator void*() const volatile
202     { return load(); }
203
204     void*
205     operator=(void* __v) // XXX volatile
206     {
207       store(__v);
208       return __v;
209     }
210
211     void*
212     operator+=(ptrdiff_t __d) volatile
213     { return fetch_add(__d) + __d; }
214
215     void*
216     operator-=(ptrdiff_t __d) volatile
217     { return fetch_sub(__d) - __d; }
218   };
219
220
221   // 29.3.1 atomic integral types
222   // For each of the integral types, define atomic_[integral type] struct
223   //
224   // atomic_bool     bool
225   // atomic_char     char
226   // atomic_schar    signed char
227   // atomic_uchar    unsigned char
228   // atomic_short    short
229   // atomic_ushort   unsigned short
230   // atomic_int      int
231   // atomic_uint     unsigned int
232   // atomic_long     long
233   // atomic_ulong    unsigned long
234   // atomic_llong    long long
235   // atomic_ullong   unsigned long long
236   // atomic_char16_t char16_t
237   // atomic_char32_t char32_t
238   // atomic_wchar_t  wchar_t
239
240   // Base type.
241   // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or 8 bytes,
242   // since that is what GCC built-in functions for atomic memory access work on.
243   template<typename _ITp>
244     struct __atomic_base
245     {
246     private:
247       typedef _ITp      __integral_type;
248
249       __integral_type   _M_i;
250
251     public:
252       __atomic_base() = default;
253       ~__atomic_base() = default;
254       __atomic_base(const __atomic_base&) = delete;
255       __atomic_base& operator=(const __atomic_base&) = delete;
256
257       // Requires __integral_type convertible to _M_base._M_i.
258       __atomic_base(__integral_type __i) { _M_i = __i; }
259
260       operator __integral_type() const volatile
261       { return load(); }
262
263       __integral_type
264       operator=(__integral_type __i) // XXX volatile
265       {
266         store(__i);
267         return __i;
268       }
269
270       __integral_type
271       operator++(int) volatile
272       { return fetch_add(1); }
273
274       __integral_type
275       operator--(int) volatile
276       { return fetch_sub(1); }
277
278       __integral_type
279       operator++() volatile
280       { return fetch_add(1) + 1; }
281
282       __integral_type
283       operator--() volatile
284       { return fetch_sub(1) - 1; }
285
286       __integral_type
287       operator+=(__integral_type __i) volatile
288       { return fetch_add(__i) + __i; }
289
290       __integral_type
291       operator-=(__integral_type __i) volatile
292       { return fetch_sub(__i) - __i; }
293
294       __integral_type
295       operator&=(__integral_type __i) volatile
296       { return fetch_and(__i) & __i; }
297
298       __integral_type
299       operator|=(__integral_type __i) volatile
300       { return fetch_or(__i) | __i; }
301
302       __integral_type
303       operator^=(__integral_type __i) volatile
304       { return fetch_xor(__i) ^ __i; }
305
306       bool
307       is_lock_free() const volatile
308       { return false; }
309
310       void
311       store(__integral_type __i,
312             memory_order __m = memory_order_seq_cst) volatile
313       {
314         __glibcxx_assert(__m != memory_order_acquire);
315         __glibcxx_assert(__m != memory_order_acq_rel);
316         __glibcxx_assert(__m != memory_order_consume);
317         _ATOMIC_STORE_(this, __i, __m);
318       }
319
320       __integral_type
321       load(memory_order __m = memory_order_seq_cst) const volatile
322       {
323         __glibcxx_assert(__m != memory_order_release);
324         __glibcxx_assert(__m != memory_order_acq_rel);
325         return _ATOMIC_LOAD_(this, __m);
326       }
327
328       __integral_type
329       exchange(__integral_type __i,
330                memory_order __m = memory_order_seq_cst) volatile
331       { return _ATOMIC_MODIFY_(this, =, __i, __m); }
332
333       bool
334       compare_exchange_weak(__integral_type& __i1, __integral_type __i2,
335                             memory_order __m1, memory_order __m2) volatile
336       {
337         __glibcxx_assert(__m2 != memory_order_release);
338         __glibcxx_assert(__m2 != memory_order_acq_rel);
339         __glibcxx_assert(__m2 <= __m1);
340         return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
341       }
342
343       bool
344       compare_exchange_weak(__integral_type& __i1, __integral_type __i2,
345                             memory_order __m = memory_order_seq_cst) volatile
346       {
347         return compare_exchange_weak(__i1, __i2, __m,
348                                      __calculate_memory_order(__m));
349       }
350
351       bool
352       compare_exchange_strong(__integral_type& __i1, __integral_type __i2,
353                               memory_order __m1, memory_order __m2) volatile
354       {
355         __glibcxx_assert(__m2 != memory_order_release);
356         __glibcxx_assert(__m2 != memory_order_acq_rel);
357         __glibcxx_assert(__m2 <= __m1);
358         return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
359       }
360
361       bool
362       compare_exchange_strong(__integral_type& __i1, __integral_type __i2,
363                               memory_order __m = memory_order_seq_cst) volatile
364       {
365         return compare_exchange_strong(__i1, __i2, __m,
366                                        __calculate_memory_order(__m));
367       }
368
369       __integral_type
370       fetch_add(__integral_type __i,
371                 memory_order __m = memory_order_seq_cst) volatile
372       { return _ATOMIC_MODIFY_(this, +=, __i, __m); }
373
374       __integral_type
375       fetch_sub(__integral_type __i,
376                 memory_order __m = memory_order_seq_cst) volatile
377       { return _ATOMIC_MODIFY_(this, -=, __i, __m); }
378
379       __integral_type
380       fetch_and(__integral_type __i,
381                 memory_order __m = memory_order_seq_cst) volatile
382       { return _ATOMIC_MODIFY_(this, &=, __i, __m); }
383
384       __integral_type
385       fetch_or(__integral_type __i,
386                memory_order __m = memory_order_seq_cst) volatile
387       { return _ATOMIC_MODIFY_(this, |=, __i, __m); }
388
389       __integral_type
390       fetch_xor(__integral_type __i,
391                 memory_order __m = memory_order_seq_cst) volatile
392       { return _ATOMIC_MODIFY_(this, ^=, __i, __m); }
393     };
394
395
396   /// atomic_bool
397   // NB: No operators or fetch-operations for this type.
398   struct atomic_bool
399   {
400   private:
401     __atomic_base<bool> _M_base;
402
403   public:
404     atomic_bool() = default;
405     ~atomic_bool() = default;
406     atomic_bool(const atomic_bool&) = delete;
407     atomic_bool& operator=(const atomic_bool&) = delete;
408
409     atomic_bool(bool __i) : _M_base(__i) { }
410
411     bool
412     operator=(bool __i) // XXX volatile
413     { return _M_base.operator=(__i); }
414
415     operator bool() const volatile
416     { return _M_base.load(); }
417
418     bool
419     is_lock_free() const volatile
420     { return _M_base.is_lock_free(); }
421
422     void
423     store(bool __i, memory_order __m = memory_order_seq_cst) volatile
424     { _M_base.store(__i, __m); }
425
426     bool
427     load(memory_order __m = memory_order_seq_cst) const volatile
428     { return _M_base.load(__m); }
429
430     bool
431     exchange(bool __i, memory_order __m = memory_order_seq_cst) volatile
432     { return _M_base.exchange(__i, __m); }
433
434     bool
435     compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1,
436                           memory_order __m2) volatile
437     { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); }
438
439     bool
440     compare_exchange_weak(bool& __i1, bool __i2,
441                           memory_order __m = memory_order_seq_cst) volatile
442     { return _M_base.compare_exchange_weak(__i1, __i2, __m); }
443
444     bool
445     compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1,
446                             memory_order __m2) volatile
447     { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); }
448
449
450     bool
451     compare_exchange_strong(bool& __i1, bool __i2,
452                             memory_order __m = memory_order_seq_cst) volatile
453     { return _M_base.compare_exchange_strong(__i1, __i2, __m); }
454   };
455
456 #undef _ATOMIC_LOAD_
457 #undef _ATOMIC_STORE_
458 #undef _ATOMIC_MODIFY_
459 #undef _ATOMIC_CMPEXCHNG_
460 } // namespace __atomic0
461
462 // _GLIBCXX_END_NAMESPACE
463
464 #endif