pion-net  4.0.9
atomic_int.hpp
1 // Copyright (C) 2007, 2008 Tim Blechmann & Thomas Grill
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 
7 // Disclaimer: Not a Boost library.
8 
9 #ifndef BOOST_LOCKFREE_ATOMIC_INT_HPP
10 #define BOOST_LOCKFREE_ATOMIC_INT_HPP
11 
12 #include <boost/lockfree/detail/prefix.hpp>
13 #include <boost/lockfree/detail/cas.hpp>
14 #include <boost/noncopyable.hpp>
15 
16 namespace boost
17 {
18 namespace lockfree
19 {
20 
21 #if defined(__GNUC__) && ( (__GNUC__ > 4) || ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)) ) || __INTEL_COMPILER
22 
23 template <typename T>
24 class atomic_int:
25  boost::noncopyable
26 {
27 public:
28  explicit atomic_int(T v = 0):
29  value(v)
30  {}
31 
32  operator T(void) const
33  {
34  return __sync_fetch_and_add(&value, 0);
35  }
36 
37  void operator =(T v)
38  {
39  value = v;
40  __sync_synchronize();
41  }
42 
43  T operator +=(T v)
44  {
45  return __sync_add_and_fetch(&value, v);
46  }
47 
48  T operator -=(T v)
49  {
50  return __sync_sub_and_fetch(&value, v);
51  }
52 
53  /* prefix operator */
54  T operator ++(void)
55  {
56  return __sync_add_and_fetch(&value, 1);
57  }
58 
59  /* prefix operator */
60  T operator --(void)
61  {
62  return __sync_sub_and_fetch(&value, 1);
63  }
64 
65  /* postfix operator */
66  T operator ++(int)
67  {
68  return __sync_fetch_and_add(&value, 1);
69  }
70 
71  /* postfix operator */
72  T operator --(int)
73  {
74  return __sync_fetch_and_sub(&value, 1);
75  }
76 
77 private:
78  mutable T value;
79 };
80 
81 #elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
82 
83 template <typename T>
84 class atomic_int:
85  boost::noncopyable
86 {
87 public:
88  explicit atomic_int(T v = 0):
89  value(v)
90  {}
91 
92  operator T(void) const
93  {
94  return __gnu_cxx::__exchange_and_add(&value, 0);
95  }
96 
97  void operator =(T v)
98  {
99  value = v;
100  }
101 
102  T operator +=(T v)
103  {
104  return __gnu_cxx::__exchange_and_add(&value, v) + v;
105  }
106 
107  T operator -=(T v)
108  {
109  return __gnu_cxx::__exchange_and_add(&value, -v) - v;
110  }
111 
112  /* prefix operator */
113  T operator ++(void)
114  {
115  return operator+=(1);
116  }
117 
118  /* prefix operator */
119  T operator --(void)
120  {
121  return operator-=(1);
122  }
123 
124  /* postfix operator */
125  T operator ++(int)
126  {
127  return __gnu_cxx::__exchange_and_add(&value, 1);
128  }
129 
130  /* postfix operator */
131  T operator --(int)
132  {
133  return __gnu_cxx::__exchange_and_add(&value, -1);
134  }
135 
136 private:
137  mutable _Atomic_word value;
138 };
139 
140 #else /* emulate via atomic_cas */
141 
142 template <typename T>
144  boost::noncopyable
145 {
146 public:
147  explicit atomic_int(T v = 0)
148  {
149  *this = v;
150  }
151 
152  operator T(void) const
153  {
154  memory_barrier();
155  return value;
156  }
157 
158  void operator =(T v)
159  {
160  value = v;
161  memory_barrier();
162  }
163 
164  /* prefix operator */
165  T operator ++()
166  {
167  return *this += 1;
168  }
169 
170  /* prefix operator */
171  T operator --()
172  {
173  return *this -= 1;
174  }
175 
176  T operator +=(T v)
177  {
178  for(;;)
179  {
180  T oldv = value;
181  T newv = oldv + v;
182  if(likely(atomic_cas(&value, oldv, newv)))
183  return newv;
184  }
185  }
186 
187  T operator -=(T v)
188  {
189  for(;;)
190  {
191  T oldv = value;
192  T newv = oldv - v;
193 
194  if(likely(atomic_cas(&value, oldv, newv)))
195  return newv;
196  }
197  }
198 
199  /* postfix operator */
200  T operator ++(int)
201  {
202  for(;;)
203  {
204  T oldv = value;
205  if(likely(atomic_cas(&value, oldv, oldv+1)))
206  return oldv;
207  }
208  }
209 
210  /* postfix operator */
211  T operator --(int)
212  {
213  for(;;)
214  {
215  T oldv = value;
216  if(likely(atomic_cas(&value, oldv, oldv-1)))
217  return oldv;
218  }
219  }
220 
221 private:
222  T value;
223 };
224 
225 
226 #endif
227 
228 } /* namespace lockfree */
229 } /* namespace boost */
230 
231 #endif /* BOOST_LOCKFREE_ATOMIC_INT_HPP */