Import gcc-4.4.1
[dragonfly.git] / contrib / gcc-4.4 / libstdc++-v3 / include / bits / atomic_2.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_2.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_2_H
32 #define _GLIBCXX_ATOMIC_2_H 1
33
34 #pragma GCC system_header
35
36 // _GLIBCXX_BEGIN_NAMESPACE(std)
37
38 // 2 == __atomic2 == Always lock-free
39 // Assumed:
40 // _GLIBCXX_ATOMIC_BUILTINS_1
41 // _GLIBCXX_ATOMIC_BUILTINS_2
42 // _GLIBCXX_ATOMIC_BUILTINS_4
43 // _GLIBCXX_ATOMIC_BUILTINS_8
44 namespace __atomic2
45 {
46   /// atomic_flag
47   struct atomic_flag : private __atomic_flag_base
48   {
49     atomic_flag() = default;
50     ~atomic_flag() = default;
51     atomic_flag(const atomic_flag&) = delete;
52     atomic_flag& operator=(const atomic_flag&) = delete;
53
54     atomic_flag(bool __i) { _M_i = __i; } // XXX deleted copy ctor != agg
55
56     bool
57     test_and_set(memory_order __m = memory_order_seq_cst) volatile
58     {
59       // Redundant synchronize if built-in for lock is a full barrier.
60       if (__m != memory_order_acquire && __m != memory_order_acq_rel)
61         __sync_synchronize();
62       return __sync_lock_test_and_set(&_M_i, 1);
63     }
64
65     void
66     clear(memory_order __m = memory_order_seq_cst) volatile
67     {
68       __glibcxx_assert(__m != memory_order_consume);
69       __glibcxx_assert(__m != memory_order_acquire);
70       __glibcxx_assert(__m != memory_order_acq_rel);
71
72       __sync_lock_release(&_M_i);
73       if (__m != memory_order_acquire && __m != memory_order_acq_rel)
74         __sync_synchronize();
75     }
76   };
77
78
79   /// 29.4.2, address types
80   struct atomic_address
81   {
82   private:
83     void* _M_i;
84
85   public:
86     atomic_address() = default;
87     ~atomic_address() = default;
88     atomic_address(const atomic_address&) = delete;
89     atomic_address& operator=(const atomic_address&) = delete;
90
91     atomic_address(void* __v) { _M_i = __v; }
92
93     bool
94     is_lock_free() const volatile
95     { return true; }
96
97     void
98     store(void* __v, memory_order __m = memory_order_seq_cst) volatile
99     {
100       __glibcxx_assert(__m != memory_order_acquire);
101       __glibcxx_assert(__m != memory_order_acq_rel);
102       __glibcxx_assert(__m != memory_order_consume);
103
104       if (__m == memory_order_relaxed)
105         _M_i = __v;
106       else
107         {
108           // write_mem_barrier();
109           _M_i = __v;
110           if (__m = memory_order_seq_cst)
111             __sync_synchronize();
112         }
113     }
114
115     void*
116     load(memory_order __m = memory_order_seq_cst) const volatile
117     {
118       __glibcxx_assert(__m != memory_order_release);
119       __glibcxx_assert(__m != memory_order_acq_rel);
120
121       __sync_synchronize();
122       void* __ret = _M_i;
123       __sync_synchronize();
124       return __ret;
125     }
126
127     void*
128     exchange(void* __v, memory_order __m = memory_order_seq_cst) volatile
129     {
130       // XXX built-in assumes memory_order_acquire.
131       return __sync_lock_test_and_set(&_M_i, __v);
132     }
133
134     bool
135     compare_exchange_weak(void*& __v1, void* __v2, memory_order __m1,
136                           memory_order __m2) volatile
137     { return compare_exchange_strong(__v1, __v2, __m1, __m2); }
138
139     bool
140     compare_exchange_weak(void*& __v1, void* __v2,
141                           memory_order __m = memory_order_seq_cst) volatile
142     {
143       return compare_exchange_weak(__v1, __v2, __m,
144                                    __calculate_memory_order(__m));
145     }
146
147     bool
148     compare_exchange_strong(void*& __v1, void* __v2, memory_order __m1,
149                             memory_order __m2) volatile
150     {
151       __glibcxx_assert(__m2 != memory_order_release);
152       __glibcxx_assert(__m2 != memory_order_acq_rel);
153       __glibcxx_assert(__m2 <= __m1);
154
155       void* __v1o = __v1;
156       void* __v1n = __sync_val_compare_and_swap(&_M_i, __v1o, __v2);
157
158       // Assume extra stores (of same value) allowed in true case.
159       __v1 = __v1n;
160       return __v1o == __v1n;
161     }
162
163     bool
164     compare_exchange_strong(void*& __v1, void* __v2,
165                           memory_order __m = memory_order_seq_cst) volatile
166     {
167       return compare_exchange_strong(__v1, __v2, __m,
168                                      __calculate_memory_order(__m));
169     }
170
171     void*
172     fetch_add(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile
173     { return __sync_fetch_and_add(&_M_i, __d); }
174
175     void*
176     fetch_sub(ptrdiff_t __d, memory_order __m = memory_order_seq_cst) volatile
177     { return __sync_fetch_and_sub(&_M_i, __d); }
178
179     operator void*() const volatile
180     { return load(); }
181
182     void*
183     operator=(void* __v) // XXX volatile
184     {
185       store(__v);
186       return __v;
187     }
188
189     void*
190     operator+=(ptrdiff_t __d) volatile
191     { return __sync_add_and_fetch(&_M_i, __d); }
192
193     void*
194     operator-=(ptrdiff_t __d) volatile
195     { return __sync_sub_and_fetch(&_M_i, __d); }
196   };
197
198   // 29.3.1 atomic integral types
199   // For each of the integral types, define atomic_[integral type] struct
200   //
201   // atomic_bool     bool
202   // atomic_char     char
203   // atomic_schar    signed char
204   // atomic_uchar    unsigned char
205   // atomic_short    short
206   // atomic_ushort   unsigned short
207   // atomic_int      int
208   // atomic_uint     unsigned int
209   // atomic_long     long
210   // atomic_ulong    unsigned long
211   // atomic_llong    long long
212   // atomic_ullong   unsigned long long
213   // atomic_char16_t char16_t
214   // atomic_char32_t char32_t
215   // atomic_wchar_t  wchar_t
216
217   // Base type.
218   // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or 8 bytes,
219   // since that is what GCC built-in functions for atomic memory access work on.
220   template<typename _ITp>
221     struct __atomic_base
222     {
223     private:
224       typedef _ITp      __integral_type;
225
226       __integral_type   _M_i;
227
228     public:
229       __atomic_base() = default;
230       ~__atomic_base() = default;
231       __atomic_base(const __atomic_base&) = delete;
232       __atomic_base& operator=(const __atomic_base&) = delete;
233
234       // Requires __integral_type convertible to _M_base._M_i.
235       __atomic_base(__integral_type __i) { _M_i = __i; }
236
237       operator __integral_type() const volatile
238       { return load(); }
239
240       __integral_type
241       operator=(__integral_type __i) // XXX volatile
242       {
243         store(__i);
244         return __i;
245       }
246
247       __integral_type
248       operator++(int) volatile
249       { return fetch_add(1); }
250
251       __integral_type
252       operator--(int) volatile
253       { return fetch_sub(1); }
254
255       __integral_type
256       operator++() volatile
257       { return __sync_add_and_fetch(&_M_i, 1); }
258
259       __integral_type
260       operator--() volatile
261       { return __sync_sub_and_fetch(&_M_i, 1); }
262
263       __integral_type
264       operator+=(__integral_type __i) volatile
265       { return __sync_add_and_fetch(&_M_i, __i); }
266
267       __integral_type
268       operator-=(__integral_type __i) volatile
269       { return __sync_sub_and_fetch(&_M_i, __i); }
270
271       __integral_type
272       operator&=(__integral_type __i) volatile
273       { return __sync_and_and_fetch(&_M_i, __i); }
274
275       __integral_type
276       operator|=(__integral_type __i) volatile
277       { return __sync_or_and_fetch(&_M_i, __i); }
278
279       __integral_type
280       operator^=(__integral_type __i) volatile
281       { return __sync_xor_and_fetch(&_M_i, __i); }
282
283       bool
284       is_lock_free() const volatile
285       { return true; }
286
287       void
288       store(__integral_type __i,
289             memory_order __m = memory_order_seq_cst) volatile
290       {
291         __glibcxx_assert(__m != memory_order_acquire);
292         __glibcxx_assert(__m != memory_order_acq_rel);
293         __glibcxx_assert(__m != memory_order_consume);
294
295         if (__m == memory_order_relaxed)
296           _M_i = __i;
297         else
298           {
299             // write_mem_barrier();
300             _M_i = __i;
301             if (__m = memory_order_seq_cst)
302               __sync_synchronize();
303           }
304       }
305
306       __integral_type
307       load(memory_order __m = memory_order_seq_cst) const volatile
308       {
309         __glibcxx_assert(__m != memory_order_release);
310         __glibcxx_assert(__m != memory_order_acq_rel);
311
312         __sync_synchronize();
313         __integral_type __ret = _M_i;
314         __sync_synchronize();
315         return __ret;
316       }
317
318       __integral_type
319       exchange(__integral_type __i,
320                memory_order __m = memory_order_seq_cst) volatile
321       {
322         // XXX built-in assumes memory_order_acquire.
323         return __sync_lock_test_and_set(&_M_i, __i);
324       }
325
326       bool
327       compare_exchange_weak(__integral_type& __i1, __integral_type __i2,
328                             memory_order __m1, memory_order __m2) volatile
329       { return compare_exchange_strong(__i1, __i2, __m1, __m2); }
330
331       bool
332       compare_exchange_weak(__integral_type& __i1, __integral_type __i2,
333                             memory_order __m = memory_order_seq_cst) volatile
334       {
335         return compare_exchange_weak(__i1, __i2, __m,
336                                      __calculate_memory_order(__m));
337       }
338
339       bool
340       compare_exchange_strong(__integral_type& __i1, __integral_type __i2,
341                               memory_order __m1, memory_order __m2) volatile
342       {
343         __glibcxx_assert(__m2 != memory_order_release);
344         __glibcxx_assert(__m2 != memory_order_acq_rel);
345         __glibcxx_assert(__m2 <= __m1);
346
347         __integral_type __i1o = __i1;
348         __integral_type __i1n = __sync_val_compare_and_swap(&_M_i, __i1o, __i2);
349
350         // Assume extra stores (of same value) allowed in true case.
351         __i1 = __i1n;
352         return __i1o == __i1n;
353       }
354
355       bool
356       compare_exchange_strong(__integral_type& __i1, __integral_type __i2,
357                               memory_order __m = memory_order_seq_cst) volatile
358       {
359         return compare_exchange_strong(__i1, __i2, __m,
360                                        __calculate_memory_order(__m));
361       }
362
363       __integral_type
364       fetch_add(__integral_type __i,
365                 memory_order __m = memory_order_seq_cst) volatile
366       { return __sync_fetch_and_add(&_M_i, __i); }
367
368       __integral_type
369       fetch_sub(__integral_type __i,
370                 memory_order __m = memory_order_seq_cst) volatile
371       { return __sync_fetch_and_sub(&_M_i, __i); }
372
373       __integral_type
374       fetch_and(__integral_type __i,
375                 memory_order __m = memory_order_seq_cst) volatile
376       { return __sync_fetch_and_and(&_M_i, __i); }
377
378       __integral_type
379       fetch_or(__integral_type __i,
380                memory_order __m = memory_order_seq_cst) volatile
381       { return __sync_fetch_and_or(&_M_i, __i); }
382
383       __integral_type
384       fetch_xor(__integral_type __i,
385                 memory_order __m = memory_order_seq_cst) volatile
386       { return __sync_fetch_and_xor(&_M_i, __i); }
387     };
388
389
390   /// atomic_bool
391   // NB: No operators or fetch-operations for this type.
392   struct atomic_bool
393   {
394   private:
395     __atomic_base<bool> _M_base;
396
397   public:
398     atomic_bool() = default;
399     ~atomic_bool() = default;
400     atomic_bool(const atomic_bool&) = delete;
401     atomic_bool& operator=(const atomic_bool&) = delete;
402
403     atomic_bool(bool __i) : _M_base(__i) { }
404
405     bool
406     operator=(bool __i) // XXX volatile
407     { return _M_base.operator=(__i); }
408
409     operator bool() const volatile
410     { return _M_base.load(); }
411
412     bool
413     is_lock_free() const volatile
414     { return _M_base.is_lock_free(); }
415
416     void
417     store(bool __i, memory_order __m = memory_order_seq_cst) volatile
418     { _M_base.store(__i, __m); }
419
420     bool
421     load(memory_order __m = memory_order_seq_cst) const volatile
422     { return _M_base.load(__m); }
423
424     bool
425     exchange(bool __i, memory_order __m = memory_order_seq_cst) volatile
426     { return _M_base.exchange(__i, __m); }
427
428     bool
429     compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1,
430                           memory_order __m2) volatile
431     { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); }
432
433     bool
434     compare_exchange_weak(bool& __i1, bool __i2,
435                           memory_order __m = memory_order_seq_cst) volatile
436     { return _M_base.compare_exchange_weak(__i1, __i2, __m); }
437
438     bool
439     compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1,
440                             memory_order __m2) volatile
441     { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); }
442
443
444     bool
445     compare_exchange_strong(bool& __i1, bool __i2,
446                             memory_order __m = memory_order_seq_cst) volatile
447     { return _M_base.compare_exchange_strong(__i1, __i2, __m); }
448   };
449 } // namespace __atomic2
450
451 // _GLIBCXX_END_NAMESPACE
452
453 #endif