OSDN Git Service

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