XRootD
Loading...
Searching...
No Matches
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
22namespace XrdSys
23{
24template<typename T>
26{
27public:
28
29// Store and fetch defined here for immediate expansion
30//
31T operator=(T v) noexcept
32 {_m.store(v, std::memory_order_relaxed); return v;}
33
34T 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//
45T operator++(int) noexcept
46 {return _m.fetch_add(1, std::memory_order_relaxed);}
47
48T operator++(int) volatile noexcept
49 {return _m.fetch_add(1, std::memory_order_relaxed);}
50
51T operator--(int) noexcept
52 {return _m.fetch_sub(1, std::memory_order_relaxed);}
53
54T operator--(int) volatile noexcept
55 {return _m.fetch_sub(1, std::memory_order_relaxed);}
56
57// Pre-increment/decrement (i.e.++x)
58//
59T operator++() noexcept
60 {return _m.fetch_add(1, std::memory_order_relaxed)+1;}
61
62T operator++() volatile noexcept
63 {return _m.fetch_add(1, std::memory_order_relaxed)+1;}
64
65T operator--() noexcept
66 {return _m.fetch_sub(1, std::memory_order_relaxed)-1;}
67
68T operator--() volatile noexcept
69 {return _m.fetch_sub(1, std::memory_order_relaxed)-1;}
70
71T operator+=(T v) noexcept
72 {return _m.fetch_add(v, std::memory_order_relaxed)+v;}
73
74T operator+=(T v) volatile noexcept
75 {return _m.fetch_add(v, std::memory_order_relaxed)+v;}
76
77T operator-=(T v) noexcept
78 {return _m.fetch_sub(v, std::memory_order_relaxed)-v;}
79
80T operator-=(T v) volatile noexcept
81 {return _m.fetch_sub(v, std::memory_order_relaxed)-v;}
82
83T operator&=(T v) noexcept
84 {return _m.fetch_and(v, std::memory_order_relaxed) & v;}
85
86T operator&=(T v) volatile noexcept
87 {return _m.fetch_and(v, std::memory_order_relaxed) & v;}
88
89T operator|=(T v) noexcept
90 {return _m.fetch_or (v, std::memory_order_relaxed) | v;}
91
92T operator|=(T v) volatile noexcept
93 {return _m.fetch_or (v, std::memory_order_relaxed) | v;}
94
95T operator^=(T v) noexcept
96 {return _m.fetch_xor(v, std::memory_order_relaxed) ^ v;}
97
98T 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//
103T fetch_and(T v) noexcept
104 {return _m.fetch_and(v, std::memory_order_relaxed);}
105
106T fetch_or(T v) noexcept
107 {return _m.fetch_or (v, std::memory_order_relaxed);}
108
109T 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
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
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
138T exchange(T v, std::memory_order mo=std::memory_order_relaxed) noexcept
139 {return _m.exchange(v, mo);}
140
141T exchange(T v, std::memory_order mo=std::memory_order_relaxed) volatile noexcept
142 {return _m.exchange(v, mo);}
143
144T load() {return _m.load(std::memory_order_relaxed);}
145
147
148 RAtomic(T v) : _m(v) {}
149
150private:
151
152std::atomic<T> _m;
153};
154
155template<typename T>
156class RAtomic<T*>
157{
158public:
159
160// Store and fetch defined here for immediate expansion
161//
162T* operator=(T* v) noexcept
163 {_m.store(v, std::memory_order_relaxed); return v;}
164
165T* operator=(T* v) volatile noexcept
166 {_m.store(v, std::memory_order_relaxed); return v;}
167
168 operator T*() noexcept
169 {return _m.load(std::memory_order_relaxed);}
170
171 operator T*() volatile noexcept
172 {return _m.load(std::memory_order_relaxed);}
173
174 T* operator->() noexcept
175 {return _m.load(std::memory_order_relaxed);}
176
177// Post-increment/decrement (i.e. x++)
178//
179T* operator++(int) noexcept
180 {return _m.fetch_add(1, std::memory_order_relaxed);}
181
182T* operator++(int) volatile noexcept
183 {return _m.fetch_add(1, std::memory_order_relaxed);}
184
185T* operator--(int) noexcept
186 {return _m.fetch_sub(1, std::memory_order_relaxed);}
187
188T* operator--(int) volatile noexcept
189 {return _m.fetch_sub(1, std::memory_order_relaxed);}
190
191// Pre-increment/decrement (i.e.++x)
192//
193T* operator++() noexcept
194 {return _m.fetch_add(1, std::memory_order_relaxed)+1;}
195
196T* operator++() volatile noexcept
197 {return _m.fetch_add(1, std::memory_order_relaxed)+1;}
198
199T* operator--() noexcept
200 {return _m.fetch_sub(1, std::memory_order_relaxed)-1;}
201
202T* operator--() volatile noexcept
203 {return _m.fetch_sub(1, std::memory_order_relaxed)-1;}
204
205T* operator+=(ptrdiff_t v) noexcept
206 {return _m.fetch_add(v, std::memory_order_relaxed)+v;}
207
208T* operator+=(ptrdiff_t v) volatile noexcept
209 {return _m.fetch_add(v, std::memory_order_relaxed)+v;}
210
211T* operator-=(ptrdiff_t v) noexcept
212 {return _m.fetch_sub(v, std::memory_order_relaxed)-v;}
213
214T* operator-=(ptrdiff_t v) volatile noexcept
215 {return _m.fetch_sub(v, std::memory_order_relaxed)-v;}
216
217// Member functions
218//
220 std::memory_order mo1=std::memory_order_relaxed,
221 std::memory_order mo2=std::memory_order_relaxed)
222 noexcept
223 {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
224
226 std::memory_order mo1=std::memory_order_relaxed,
227 std::memory_order mo2=std::memory_order_relaxed)
228 volatile noexcept
229 {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
230
231T* compare_exchange_weak(T& v1, T* v2,
232 std::memory_order mo1=std::memory_order_relaxed,
233 std::memory_order mo2=std::memory_order_relaxed)
234 noexcept
235 {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
236
237T* compare_exchange_weak(T& v1, T* v2,
238 std::memory_order mo1=std::memory_order_relaxed,
239 std::memory_order mo2=std::memory_order_relaxed)
240 volatile noexcept
241 {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
242
243T* exchange(T* v, std::memory_order mo=std::memory_order_relaxed) noexcept
244 {return _m.exchange(v, mo);}
245
246T* exchange(T* v, std::memory_order mo=std::memory_order_relaxed) volatile noexcept
247 {return _m.exchange(v, mo);}
248
250
251 RAtomic(T* v) : _m(v) {}
252
253private:
254
255std::atomic<T*> _m;
256};
257
258template<>
259class RAtomic<bool>
260{
261public:
262
263// Store and fetch defined here for immediate expansion
264//
265bool operator=(bool v) noexcept
266 {_m.store(v, std::memory_order_relaxed); return v;}
267
268bool operator=(bool v) volatile noexcept
269 {_m.store(v, std::memory_order_relaxed); return v;}
270
271 operator bool() noexcept
272 {return _m.load(std::memory_order_relaxed);}
273
274 operator bool() volatile noexcept
275 {return _m.load(std::memory_order_relaxed);}
276
277// Member functions
278//
279bool compare_exchange_strong(bool& v1, bool v2,
280 std::memory_order mo1=std::memory_order_relaxed,
281 std::memory_order mo2=std::memory_order_relaxed)
282 noexcept
283 {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
284
285bool compare_exchange_strong(bool& v1, bool v2,
286 std::memory_order mo1=std::memory_order_relaxed,
287 std::memory_order mo2=std::memory_order_relaxed)
288 volatile noexcept
289 {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
290
291bool compare_exchange_weak(bool& v1, bool v2,
292 std::memory_order mo1=std::memory_order_relaxed,
293 std::memory_order mo2=std::memory_order_relaxed)
294 noexcept
295 {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
296
297bool compare_exchange_weak(bool& v1, bool v2,
298 std::memory_order mo1=std::memory_order_relaxed,
299 std::memory_order mo2=std::memory_order_relaxed)
300 volatile noexcept
301 {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
302
303bool exchange(bool v, std::memory_order mo=std::memory_order_relaxed) noexcept
304 {return _m.exchange(v, mo);}
305
306bool exchange(bool v, std::memory_order mo=std::memory_order_relaxed) volatile noexcept
307 {return _m.exchange(v, mo);}
308
309bool load() {return _m.load(std::memory_order_relaxed);}
310
312
313 RAtomic(bool v) : _m(v) {}
314
315private:
316
317std::atomic<bool> _m;
318};
319}
320
321// Common types
322//
344#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 * exchange(T *v, std::memory_order mo=std::memory_order_relaxed) 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 * 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--() 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) noexcept
T * operator--() noexcept
T * operator+=(ptrdiff_t v) noexcept
T * operator-=(ptrdiff_t v) volatile noexcept
T * operator--(int) noexcept
T * operator-=(ptrdiff_t v) noexcept
T * operator++() noexcept
T * operator=(T *v) noexcept
T * operator->() noexcept
T * operator+=(ptrdiff_t v) volatile noexcept
T * operator=(T *v) volatile noexcept
T * operator++() volatile noexcept
T * operator++(int) noexcept
T * exchange(T *v, std::memory_order mo=std::memory_order_relaxed) volatile noexcept
T * operator--(int) 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
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