XRootD
XrdSysRAtomic.hh
Go to the documentation of this file.
1 #ifndef __XRDSYSRATOMIC__HH
2 #define __XRDSYSRATOMIC__HH
3 /******************************************************************************/
4 /* */
5 /* X r d S y s R A t o m i c . h h */
6 /* */
7 /******************************************************************************/
8 
9 /* The XrdSys::RAtomic class can be used to define an integral, pointer, or
10  boolean type atomic variable that use relaxed memory order by default. In
11  general all atomics should use relaxed memory order and when more than one
12  such variable needs to be synchronized these should be done using a lock.
13  The server/client architecture do not require nor should require multiple
14  variable ordering consistency in the presence of atomics. This is done to
15  make it clear which variable are co-dependent in terms of atomic access.
16 */
17 
18 #include <atomic>
19 #include <cstddef>
20 #include <cstdint>
21 
22 namespace XrdSys
23 {
24 template<typename T>
25 class RAtomic
26 {
27 public:
28 
29 // Store and fetch defined here for immediate expansion
30 //
31 T operator=(T v) noexcept
32  {_m.store(v, std::memory_order_relaxed); return v;}
33 
34 T operator=(T v) volatile noexcept
35  {_m.store(v, std::memory_order_relaxed); return v;}
36 
37  operator T() noexcept
38  {return _m.load(std::memory_order_relaxed);}
39 
40  operator T() volatile noexcept
41  {return _m.load(std::memory_order_relaxed);}
42 
43 // Post-increment/decrement (i.e. x++)
44 //
45 T operator++(int) noexcept
46  {return _m.fetch_add(1, std::memory_order_relaxed);}
47 
48 T operator++(int) volatile noexcept
49  {return _m.fetch_add(1, std::memory_order_relaxed);}
50 
51 T operator--(int) noexcept
52  {return _m.fetch_sub(1, std::memory_order_relaxed);}
53 
54 T operator--(int) volatile noexcept
55  {return _m.fetch_sub(1, std::memory_order_relaxed);}
56 
57 // Pre-increment/decrement (i.e.++x)
58 //
59 T operator++() noexcept
60  {return _m.fetch_add(1, std::memory_order_relaxed)+1;}
61 
62 T operator++() volatile noexcept
63  {return _m.fetch_add(1, std::memory_order_relaxed)+1;}
64 
65 T operator--() noexcept
66  {return _m.fetch_sub(1, std::memory_order_relaxed)-1;}
67 
68 T operator--() volatile noexcept
69  {return _m.fetch_sub(1, std::memory_order_relaxed)-1;}
70 
71 T operator+=(T v) noexcept
72  {return _m.fetch_add(v, std::memory_order_relaxed)+v;}
73 
74 T operator+=(T v) volatile noexcept
75  {return _m.fetch_add(v, std::memory_order_relaxed)+v;}
76 
77 T operator-=(T v) noexcept
78  {return _m.fetch_sub(v, std::memory_order_relaxed)-v;}
79 
80 T operator-=(T v) volatile noexcept
81  {return _m.fetch_sub(v, std::memory_order_relaxed)-v;}
82 
83 T operator&=(T v) noexcept
84  {return _m.fetch_and(v, std::memory_order_relaxed) & v;}
85 
86 T operator&=(T v) volatile noexcept
87  {return _m.fetch_and(v, std::memory_order_relaxed) & v;}
88 
89 T operator|=(T v) noexcept
90  {return _m.fetch_or (v, std::memory_order_relaxed) | v;}
91 
92 T operator|=(T v) volatile noexcept
93  {return _m.fetch_or (v, std::memory_order_relaxed) | v;}
94 
95 T operator^=(T v) noexcept
96  {return _m.fetch_xor(v, std::memory_order_relaxed) ^ v;}
97 
98 T operator^=(T v) volatile noexcept
99  {return _m.fetch_xor(v, std::memory_order_relaxed) ^ v;}
100 
101 // Specialty functions that fetch and do a post operation
102 //
103 T fetch_and(T v) noexcept
104  {return _m.fetch_and(v, std::memory_order_relaxed);}
105 
106 T fetch_or(T v) noexcept
107  {return _m.fetch_or (v, std::memory_order_relaxed);}
108 
109 T fetch_xor(T v) noexcept
110  {return _m.fetch_xor(v, std::memory_order_relaxed);}
111 
112 // Member functions
113 //
115  std::memory_order mo1=std::memory_order_relaxed,
116  std::memory_order mo2=std::memory_order_relaxed)
117  noexcept
118  {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
119 
121  std::memory_order mo1=std::memory_order_relaxed,
122  std::memory_order mo2=std::memory_order_relaxed)
123  volatile noexcept
124  {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
125 
126 T compare_exchange_weak(T& v1, T v2,
127  std::memory_order mo1=std::memory_order_relaxed,
128  std::memory_order mo2=std::memory_order_relaxed)
129  noexcept
130  {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
131 
132 T compare_exchange_weak(T& v1, T v2,
133  std::memory_order mo1=std::memory_order_relaxed,
134  std::memory_order mo2=std::memory_order_relaxed)
135  volatile noexcept
136  {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
137 
138 T exchange(T v, std::memory_order mo=std::memory_order_relaxed) noexcept
139  {return _m.exchange(v, mo);}
140 
141 T exchange(T v, std::memory_order mo=std::memory_order_relaxed) volatile noexcept
142  {return _m.exchange(v, mo);}
143 
144  RAtomic() {}
145 
146  RAtomic(T v) : _m(v) {}
147 
148 private:
149 
150 std::atomic<T> _m;
151 };
152 
153 template<typename T>
154 class RAtomic<T*>
155 {
156 public:
157 
158 // Store and fetch defined here for immediate expansion
159 //
160 T* operator=(T* v) noexcept
161  {_m.store(v, std::memory_order_relaxed); return v;}
162 
163 T* operator=(T* v) volatile noexcept
164  {_m.store(v, std::memory_order_relaxed); return v;}
165 
166  operator T*() noexcept
167  {return _m.load(std::memory_order_relaxed);}
168 
169  operator T*() volatile noexcept
170  {return _m.load(std::memory_order_relaxed);}
171 
172  T* operator->() noexcept
173  {return _m.load(std::memory_order_relaxed);}
174 
175 // Post-increment/decrement (i.e. x++)
176 //
177 T* operator++(int) noexcept
178  {return _m.fetch_add(1, std::memory_order_relaxed);}
179 
180 T* operator++(int) volatile noexcept
181  {return _m.fetch_add(1, std::memory_order_relaxed);}
182 
183 T* operator--(int) noexcept
184  {return _m.fetch_sub(1, std::memory_order_relaxed);}
185 
186 T* operator--(int) volatile noexcept
187  {return _m.fetch_sub(1, std::memory_order_relaxed);}
188 
189 // Pre-increment/decrement (i.e.++x)
190 //
191 T* operator++() noexcept
192  {return _m.fetch_add(1, std::memory_order_relaxed)+1;}
193 
194 T* operator++() volatile noexcept
195  {return _m.fetch_add(1, std::memory_order_relaxed)+1;}
196 
197 T* operator--() noexcept
198  {return _m.fetch_sub(1, std::memory_order_relaxed)-1;}
199 
200 T* operator--() volatile noexcept
201  {return _m.fetch_sub(1, std::memory_order_relaxed)-1;}
202 
203 T* operator+=(ptrdiff_t v) noexcept
204  {return _m.fetch_add(v, std::memory_order_relaxed)+v;}
205 
206 T* operator+=(ptrdiff_t v) volatile noexcept
207  {return _m.fetch_add(v, std::memory_order_relaxed)+v;}
208 
209 T* operator-=(ptrdiff_t v) noexcept
210  {return _m.fetch_sub(v, std::memory_order_relaxed)-v;}
211 
212 T* operator-=(ptrdiff_t v) volatile noexcept
213  {return _m.fetch_sub(v, std::memory_order_relaxed)-v;}
214 
215 // Member functions
216 //
217 T* compare_exchange_strong(T& v1, T* v2,
218  std::memory_order mo1=std::memory_order_relaxed,
219  std::memory_order mo2=std::memory_order_relaxed)
220  noexcept
221  {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
222 
223 T* compare_exchange_strong(T& v1, T* v2,
224  std::memory_order mo1=std::memory_order_relaxed,
225  std::memory_order mo2=std::memory_order_relaxed)
226  volatile noexcept
227  {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
228 
229 T* compare_exchange_weak(T& v1, T* v2,
230  std::memory_order mo1=std::memory_order_relaxed,
231  std::memory_order mo2=std::memory_order_relaxed)
232  noexcept
233  {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
234 
235 T* compare_exchange_weak(T& v1, T* v2,
236  std::memory_order mo1=std::memory_order_relaxed,
237  std::memory_order mo2=std::memory_order_relaxed)
238  volatile noexcept
239  {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
240 
241 T* exchange(T* v, std::memory_order mo=std::memory_order_relaxed) noexcept
242  {return _m.exchange(v, mo);}
243 
244 T* exchange(T* v, std::memory_order mo=std::memory_order_relaxed) volatile noexcept
245  {return _m.exchange(v, mo);}
246 
247  RAtomic() {}
248 
249  RAtomic(T* v) : _m(v) {}
250 
251 private:
252 
253 std::atomic<T*> _m;
254 };
255 
256 template<>
257 class RAtomic<bool>
258 {
259 public:
260 
261 // Store and fetch defined here for immediate expansion
262 //
263 bool operator=(bool v) noexcept
264  {_m.store(v, std::memory_order_relaxed); return v;}
265 
266 bool operator=(bool v) volatile noexcept
267  {_m.store(v, std::memory_order_relaxed); return v;}
268 
269  operator bool() noexcept
270  {return _m.load(std::memory_order_relaxed);}
271 
272  operator bool() volatile noexcept
273  {return _m.load(std::memory_order_relaxed);}
274 
275 // Member functions
276 //
277 bool compare_exchange_strong(bool& v1, bool v2,
278  std::memory_order mo1=std::memory_order_relaxed,
279  std::memory_order mo2=std::memory_order_relaxed)
280  noexcept
281  {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
282 
283 bool compare_exchange_strong(bool& v1, bool v2,
284  std::memory_order mo1=std::memory_order_relaxed,
285  std::memory_order mo2=std::memory_order_relaxed)
286  volatile noexcept
287  {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
288 
289 bool compare_exchange_weak(bool& v1, bool v2,
290  std::memory_order mo1=std::memory_order_relaxed,
291  std::memory_order mo2=std::memory_order_relaxed)
292  noexcept
293  {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
294 
295 bool compare_exchange_weak(bool& v1, bool v2,
296  std::memory_order mo1=std::memory_order_relaxed,
297  std::memory_order mo2=std::memory_order_relaxed)
298  volatile noexcept
299  {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
300 
301 bool exchange(bool v, std::memory_order mo=std::memory_order_relaxed) noexcept
302  {return _m.exchange(v, mo);}
303 
304 bool exchange(bool v, std::memory_order mo=std::memory_order_relaxed) volatile noexcept
305  {return _m.exchange(v, mo);}
306 
307  RAtomic() {}
308 
309  RAtomic(bool v) : _m(v) {}
310 
311 private:
312 
313 std::atomic<bool> _m;
314 };
315 }
316 
317 // Common types
318 //
340 #endif
XrdSys::RAtomic< unsigned char > RAtomic_uchar
XrdSys::RAtomic< uint64_t > RAtomic_uint64_t
XrdSys::RAtomic< short > RAtomic_short
XrdSys::RAtomic< bool > RAtomic_bool
XrdSys::RAtomic< char > RAtomic_char
XrdSys::RAtomic< wchar_t > RAtomic_wchar_t
XrdSys::RAtomic< long long > RAtomic_llong
XrdSys::RAtomic< uint32_t > RAtomic_uint32_t
XrdSys::RAtomic< int16_t > RAtomic_int16_t
XrdSys::RAtomic< uint8_t > RAtomic_uint8_t
XrdSys::RAtomic< int32_t > RAtomic_int32_t
XrdSys::RAtomic< uint16_t > RAtomic_uint16_t
XrdSys::RAtomic< long > RAtomic_long
XrdSys::RAtomic< unsigned long long > RAtomic_ullong
XrdSys::RAtomic< unsigned short > RAtomic_ushort
XrdSys::RAtomic< int64_t > RAtomic_int64_t
XrdSys::RAtomic< unsigned int > RAtomic_uint
XrdSys::RAtomic< unsigned long > RAtomic_ulong
XrdSys::RAtomic< signed char > RAtomic_schar
XrdSys::RAtomic< int > RAtomic_int
XrdSys::RAtomic< int8_t > RAtomic_int8_t
T * compare_exchange_weak(T &v1, T *v2, std::memory_order mo1=std::memory_order_relaxed, std::memory_order mo2=std::memory_order_relaxed) noexcept
T * operator--(int) noexcept
T * operator++(int) noexcept
T * exchange(T *v, std::memory_order mo=std::memory_order_relaxed) noexcept
T * operator++(int) volatile noexcept
T * operator++() volatile noexcept
T * operator--() volatile noexcept
T * operator--() noexcept
T * operator-=(ptrdiff_t v) noexcept
T * operator=(T *v) volatile noexcept
T * operator--(int) volatile noexcept
T * compare_exchange_strong(T &v1, T *v2, std::memory_order mo1=std::memory_order_relaxed, std::memory_order mo2=std::memory_order_relaxed) volatile noexcept
T * operator=(T *v) noexcept
T * operator+=(ptrdiff_t v) noexcept
T * compare_exchange_strong(T &v1, T *v2, std::memory_order mo1=std::memory_order_relaxed, std::memory_order mo2=std::memory_order_relaxed) noexcept
T * operator++() noexcept
T * operator->() noexcept
T * operator-=(ptrdiff_t v) volatile noexcept
T * exchange(T *v, std::memory_order mo=std::memory_order_relaxed) volatile noexcept
T * compare_exchange_weak(T &v1, T *v2, std::memory_order mo1=std::memory_order_relaxed, std::memory_order mo2=std::memory_order_relaxed) volatile noexcept
T * operator+=(ptrdiff_t v) volatile noexcept
bool operator=(bool v) noexcept
bool operator=(bool v) volatile noexcept
bool exchange(bool v, std::memory_order mo=std::memory_order_relaxed) noexcept
bool compare_exchange_weak(bool &v1, bool v2, std::memory_order mo1=std::memory_order_relaxed, std::memory_order mo2=std::memory_order_relaxed) volatile noexcept
bool compare_exchange_strong(bool &v1, bool v2, std::memory_order mo1=std::memory_order_relaxed, std::memory_order mo2=std::memory_order_relaxed) volatile noexcept
bool compare_exchange_weak(bool &v1, bool v2, std::memory_order mo1=std::memory_order_relaxed, std::memory_order mo2=std::memory_order_relaxed) noexcept
bool exchange(bool v, std::memory_order mo=std::memory_order_relaxed) volatile noexcept
bool compare_exchange_strong(bool &v1, bool v2, std::memory_order mo1=std::memory_order_relaxed, std::memory_order mo2=std::memory_order_relaxed) noexcept
T operator++(int) noexcept
T operator^=(T v) noexcept
T operator+=(T v) noexcept
T operator&=(T v) volatile noexcept
T fetch_or(T v) noexcept
T operator=(T v) noexcept
T operator--(int) noexcept
T exchange(T v, std::memory_order mo=std::memory_order_relaxed) volatile noexcept
T operator|=(T v) volatile noexcept
T compare_exchange_weak(T &v1, T v2, std::memory_order mo1=std::memory_order_relaxed, std::memory_order mo2=std::memory_order_relaxed) volatile noexcept
T fetch_xor(T v) noexcept
T operator=(T v) volatile noexcept
T fetch_and(T v) noexcept
T compare_exchange_weak(T &v1, T v2, std::memory_order mo1=std::memory_order_relaxed, std::memory_order mo2=std::memory_order_relaxed) noexcept
T operator--(int) volatile noexcept
T operator&=(T v) noexcept
T operator++() volatile noexcept
T operator--() volatile noexcept
T exchange(T v, std::memory_order mo=std::memory_order_relaxed) noexcept
T compare_exchange_strong(T &v1, T v2, std::memory_order mo1=std::memory_order_relaxed, std::memory_order mo2=std::memory_order_relaxed) noexcept
T compare_exchange_strong(T &v1, T v2, std::memory_order mo1=std::memory_order_relaxed, std::memory_order mo2=std::memory_order_relaxed) volatile noexcept
T operator--() noexcept
T operator^=(T v) volatile noexcept
T operator|=(T v) noexcept
T operator-=(T v) noexcept
T operator++() noexcept
T operator-=(T v) volatile noexcept
T operator+=(T v) volatile noexcept
T operator++(int) volatile noexcept