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() const noexcept
41 {return _m.load(std::memory_order_relaxed);}
42
43 operator T() volatile noexcept
44 {return _m.load(std::memory_order_relaxed);}
45
46 operator T() const volatile noexcept
47 {return _m.load(std::memory_order_relaxed);}
48
49 // Assignment operators
50
51 RAtomic& operator=(const RAtomic& other) noexcept {
52 if (this != &other) {
53 _m.store(other._m.load(std::memory_order_relaxed), std::memory_order_relaxed);
54 }
55 return *this;
56 }
57
58 RAtomic& operator=(const RAtomic& other) volatile noexcept {
59 if (this != &other) {
60 _m.store(other._m.load(std::memory_order_relaxed), std::memory_order_relaxed);
61 }
62 return *this;
63 }
64
65// Post-increment/decrement (i.e. x++)
66//
67T operator++(int) noexcept
68 {return _m.fetch_add(1, std::memory_order_relaxed);}
69
70T operator++(int) volatile noexcept
71 {return _m.fetch_add(1, std::memory_order_relaxed);}
72
73T operator--(int) noexcept
74 {return _m.fetch_sub(1, std::memory_order_relaxed);}
75
76T operator--(int) volatile noexcept
77 {return _m.fetch_sub(1, std::memory_order_relaxed);}
78
79// Pre-increment/decrement (i.e.++x)
80//
81T operator++() noexcept
82 {return _m.fetch_add(1, std::memory_order_relaxed)+1;}
83
84T operator++() volatile noexcept
85 {return _m.fetch_add(1, std::memory_order_relaxed)+1;}
86
87T operator--() noexcept
88 {return _m.fetch_sub(1, std::memory_order_relaxed)-1;}
89
90T operator--() volatile noexcept
91 {return _m.fetch_sub(1, std::memory_order_relaxed)-1;}
92
93T operator+=(T v) noexcept
94 {return _m.fetch_add(v, std::memory_order_relaxed)+v;}
95
96T operator+=(T v) volatile noexcept
97 {return _m.fetch_add(v, std::memory_order_relaxed)+v;}
98
99T operator-=(T v) noexcept
100 {return _m.fetch_sub(v, std::memory_order_relaxed)-v;}
101
102T operator-=(T v) volatile noexcept
103 {return _m.fetch_sub(v, std::memory_order_relaxed)-v;}
104
105T operator&=(T v) noexcept
106 {return _m.fetch_and(v, std::memory_order_relaxed) & v;}
107
108T operator&=(T v) volatile noexcept
109 {return _m.fetch_and(v, std::memory_order_relaxed) & v;}
110
111T operator|=(T v) noexcept
112 {return _m.fetch_or (v, std::memory_order_relaxed) | v;}
113
114T operator|=(T v) volatile noexcept
115 {return _m.fetch_or (v, std::memory_order_relaxed) | v;}
116
117T operator^=(T v) noexcept
118 {return _m.fetch_xor(v, std::memory_order_relaxed) ^ v;}
119
120T operator^=(T v) volatile noexcept
121 {return _m.fetch_xor(v, std::memory_order_relaxed) ^ v;}
122
123// Specialty functions that fetch and do a post operation
124//
125T fetch_and(T v) noexcept
126 {return _m.fetch_and(v, std::memory_order_relaxed);}
127
128T fetch_or(T v) noexcept
129 {return _m.fetch_or (v, std::memory_order_relaxed);}
130
131T fetch_xor(T v) noexcept
132 {return _m.fetch_xor(v, std::memory_order_relaxed);}
133
134// Member functions
135//
137 std::memory_order mo1=std::memory_order_relaxed,
138 std::memory_order mo2=std::memory_order_relaxed)
139 noexcept
140 {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
141
143 std::memory_order mo1=std::memory_order_relaxed,
144 std::memory_order mo2=std::memory_order_relaxed)
145 volatile noexcept
146 {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
147
149 std::memory_order mo1=std::memory_order_relaxed,
150 std::memory_order mo2=std::memory_order_relaxed)
151 noexcept
152 {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
153
155 std::memory_order mo1=std::memory_order_relaxed,
156 std::memory_order mo2=std::memory_order_relaxed)
157 volatile noexcept
158 {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
159
160T exchange(T v, std::memory_order mo=std::memory_order_relaxed) noexcept
161 {return _m.exchange(v, mo);}
162
163T exchange(T v, std::memory_order mo=std::memory_order_relaxed) volatile noexcept
164 {return _m.exchange(v, mo);}
165
167
168 RAtomic(T v) : _m(v) {}
169
170private:
171
172std::atomic<T> _m;
173};
174
175template<typename T>
176class RAtomic<T*>
177{
178public:
179
180// Store and fetch defined here for immediate expansion
181//
182T* operator=(T* v) noexcept
183 {_m.store(v, std::memory_order_relaxed); return v;}
184
185T* operator=(T* v) volatile noexcept
186 {_m.store(v, std::memory_order_relaxed); return v;}
187
188 operator T*() noexcept
189 {return _m.load(std::memory_order_relaxed);}
190
191 operator T*() volatile noexcept
192 {return _m.load(std::memory_order_relaxed);}
193
194 T* operator->() noexcept
195 {return _m.load(std::memory_order_relaxed);}
196
197// Post-increment/decrement (i.e. x++)
198//
199T* operator++(int) noexcept
200 {return _m.fetch_add(1, std::memory_order_relaxed);}
201
202T* operator++(int) volatile noexcept
203 {return _m.fetch_add(1, std::memory_order_relaxed);}
204
205T* operator--(int) noexcept
206 {return _m.fetch_sub(1, std::memory_order_relaxed);}
207
208T* operator--(int) volatile noexcept
209 {return _m.fetch_sub(1, std::memory_order_relaxed);}
210
211// Pre-increment/decrement (i.e.++x)
212//
213T* operator++() noexcept
214 {return _m.fetch_add(1, std::memory_order_relaxed)+1;}
215
216T* operator++() volatile noexcept
217 {return _m.fetch_add(1, std::memory_order_relaxed)+1;}
218
219T* operator--() noexcept
220 {return _m.fetch_sub(1, std::memory_order_relaxed)-1;}
221
222T* operator--() volatile noexcept
223 {return _m.fetch_sub(1, std::memory_order_relaxed)-1;}
224
225T* operator+=(ptrdiff_t v) noexcept
226 {return _m.fetch_add(v, std::memory_order_relaxed)+v;}
227
228T* operator+=(ptrdiff_t v) volatile noexcept
229 {return _m.fetch_add(v, std::memory_order_relaxed)+v;}
230
231T* operator-=(ptrdiff_t v) noexcept
232 {return _m.fetch_sub(v, std::memory_order_relaxed)-v;}
233
234T* operator-=(ptrdiff_t v) volatile noexcept
235 {return _m.fetch_sub(v, std::memory_order_relaxed)-v;}
236
237// Member functions
238//
240 std::memory_order mo1=std::memory_order_relaxed,
241 std::memory_order mo2=std::memory_order_relaxed)
242 noexcept
243 {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
244
246 std::memory_order mo1=std::memory_order_relaxed,
247 std::memory_order mo2=std::memory_order_relaxed)
248 volatile noexcept
249 {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
250
251T* compare_exchange_weak(T& v1, T* v2,
252 std::memory_order mo1=std::memory_order_relaxed,
253 std::memory_order mo2=std::memory_order_relaxed)
254 noexcept
255 {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
256
257T* compare_exchange_weak(T& v1, T* v2,
258 std::memory_order mo1=std::memory_order_relaxed,
259 std::memory_order mo2=std::memory_order_relaxed)
260 volatile noexcept
261 {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
262
263T* exchange(T* v, std::memory_order mo=std::memory_order_relaxed) noexcept
264 {return _m.exchange(v, mo);}
265
266T* exchange(T* v, std::memory_order mo=std::memory_order_relaxed) volatile noexcept
267 {return _m.exchange(v, mo);}
268
270
271 RAtomic(T* v) : _m(v) {}
272
273private:
274
275std::atomic<T*> _m;
276};
277
278template<>
279class RAtomic<bool>
280{
281public:
282
283// Store and fetch defined here for immediate expansion
284//
285bool operator=(bool v) noexcept
286 {_m.store(v, std::memory_order_relaxed); return v;}
287
288bool operator=(bool v) volatile noexcept
289 {_m.store(v, std::memory_order_relaxed); return v;}
290
291 operator bool() noexcept
292 {return _m.load(std::memory_order_relaxed);}
293
294 operator bool() volatile noexcept
295 {return _m.load(std::memory_order_relaxed);}
296
297// Member functions
298//
299bool compare_exchange_strong(bool& v1, bool v2,
300 std::memory_order mo1=std::memory_order_relaxed,
301 std::memory_order mo2=std::memory_order_relaxed)
302 noexcept
303 {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
304
305bool compare_exchange_strong(bool& v1, bool v2,
306 std::memory_order mo1=std::memory_order_relaxed,
307 std::memory_order mo2=std::memory_order_relaxed)
308 volatile noexcept
309 {return _m.compare_exchange_strong(v1, v2, mo1, mo2);}
310
311bool compare_exchange_weak(bool& v1, bool v2,
312 std::memory_order mo1=std::memory_order_relaxed,
313 std::memory_order mo2=std::memory_order_relaxed)
314 noexcept
315 {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
316
317bool compare_exchange_weak(bool& v1, bool v2,
318 std::memory_order mo1=std::memory_order_relaxed,
319 std::memory_order mo2=std::memory_order_relaxed)
320 volatile noexcept
321 {return _m.compare_exchange_weak(v1, v2, mo1, mo2);}
322
323bool exchange(bool v, std::memory_order mo=std::memory_order_relaxed) noexcept
324 {return _m.exchange(v, mo);}
325
326bool exchange(bool v, std::memory_order mo=std::memory_order_relaxed) volatile noexcept
327 {return _m.exchange(v, mo);}
328
329 RAtomic() {}
330
331 RAtomic(bool v) : _m(v) {}
332
333private:
334
335std::atomic<bool> _m;
336};
337}
338
339// Common types
340//
362#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
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
RAtomic & operator=(const RAtomic &other) noexcept
T operator-=(T v) noexcept
T operator++() noexcept
T operator-=(T v) volatile noexcept
T operator+=(T v) volatile noexcept
RAtomic & operator=(const RAtomic &other) volatile noexcept
T operator++(int) volatile noexcept