40#ifndef G4atomic_defines_hh_
41#define G4atomic_defines_hh_
60 template <
typename _Tp>
61 using OpFunction = std::function<_Tp(
const _Tp&,
const _Tp&)>;
63 template <
typename _Tp>
64 inline void do_fetch_and_store(std::atomic<_Tp>* _atomic,
const _Tp& _value,
65 std::memory_order mem_odr)
67 _atomic->store(_value, mem_odr);
70 template <
typename _Tp>
71 inline void do_fetch_and_store(std::atomic<_Tp>* _atomic,
72 const std::atomic<_Tp>& _value,
73 std::memory_order mem_odr)
75 _atomic->store(_value.load(), mem_odr);
78 template <
typename _Tp>
79 inline void do_compare_and_swap(std::atomic<_Tp>* _atomic,
81 const OpFunction<_Tp>& _operator,
82 std::memory_order mem_odr)
84 _Tp _expected = _Tp();
87 _expected = _atomic->load();
88 }
while(!(_atomic->compare_exchange_weak(
89 _expected, _operator(_expected, _value), mem_odr)));
92 template <
typename _Tp>
93 inline void do_compare_and_swap(std::atomic<_Tp>* _atomic,
94 const std::atomic<_Tp>& _atomic_value,
95 const OpFunction<_Tp>& _operator,
96 std::memory_order mem_odr)
98 _Tp _expected = _Tp();
101 _expected = _atomic->load();
102 }
while(!(_atomic->compare_exchange_weak(
103 _expected, _operator(_expected, _atomic_value.load()), mem_odr)));
110 template <
typename T>
111 inline void set(std::atomic<T>* _atomic,
const T& _desired,
112 std::memory_order mem_odr = std::memory_order_seq_cst)
114 details::do_compare_and_swap(
116 details::OpFunction<T>([](
const T&,
const T& y) {
return y; }), mem_odr);
119 template <
typename T>
120 inline void set(std::atomic<T>& _atomic,
const T& _desired,
121 std::memory_order mem_odr = std::memory_order_seq_cst)
123 set(&_atomic, _desired, mem_odr);
126 template <
typename T>
127 inline void increment(std::atomic<T>* _atomic,
const T& _increment,
128 std::memory_order mem_odr)
130 details::do_compare_and_swap(
132 details::OpFunction<T>([](
const T& x,
const T& y) {
return x + y; }),
136 template <
typename T>
137 inline void decrement(std::atomic<T>* _atomic,
const T& _decrement,
138 std::memory_order mem_odr)
140 details::do_compare_and_swap(
142 details::OpFunction<T>([](
const T& x,
const T& y) {
return x - y; }),
146 template <
typename T>
147 inline void multiply(std::atomic<T>* _atomic,
const T& _factor,
148 std::memory_order mem_odr)
150 details::do_compare_and_swap(
152 details::OpFunction<T>([](
const T& x,
const T& y) {
return x * y; }),
156 template <
typename T>
157 inline void divide(std::atomic<T>* _atomic,
const T& _factor,
158 std::memory_order mem_odr)
160 details::do_compare_and_swap(
162 details::OpFunction<T>([](
const T& x,
const T& y) {
return x / y; }),
168 template <
typename T>
169 inline void set(std::atomic<T>* _atomic,
170 const std::atomic<T>& _atomic_desired,
171 std::memory_order mem_odr = std::memory_order_seq_cst)
174 details::do_compare_and_swap(
175 _atomic, _atomic_desired,
176 details::OpFunction<T>([](
const T&,
const T& y) {
return y; }), mem_odr);
179 template <
typename T>
180 inline void set(std::atomic<T>& _atomic,
181 const std::atomic<T>& _atomic_desired,
182 std::memory_order mem_odr)
184 set(&_atomic, _atomic_desired, mem_odr);
187 template <
typename T>
188 inline void increment(std::atomic<T>* _atomic,
189 const std::atomic<T>& _atomic_increment,
190 std::memory_order mem_odr)
192 details::do_compare_and_swap(
193 _atomic, _atomic_increment,
194 details::OpFunction<T>([](
const T& x,
const T& y) {
return x + y; }),
198 template <
typename T>
199 inline void decrement(std::atomic<T>* _atomic,
200 const std::atomic<T>& _atomic_decrement,
201 std::memory_order mem_odr)
203 details::do_compare_and_swap(
204 _atomic, _atomic_decrement,
205 details::OpFunction<T>([](
const T& x,
const T& y) {
return x - y; }),
209 template <
typename T>
210 inline void multiply(std::atomic<T>* _atomic,
211 const std::atomic<T>& _atomic_factor,
212 std::memory_order mem_odr)
214 details::do_compare_and_swap(
215 _atomic, _atomic_factor,
216 details::OpFunction<T>([](
const T& x,
const T& y) {
return x * y; }),
220 template <
typename T>
221 inline void divide(std::atomic<T>* _atomic,
222 const std::atomic<T>& _atomic_factor,
223 std::memory_order mem_odr)
225 details::do_compare_and_swap(
226 _atomic, _atomic_factor,
227 details::OpFunction<T>([](
const T& x,
const T& y) {
return x / y; }),
234 template <
typename T>
235 inline void set(T* _non_atomic,
const T& _desired)
237 *_non_atomic = _desired;
240 template <
typename T>
241 inline void set(T& _non_atomic,
const T& _desired)
243 set(&_non_atomic, _desired);
252 template <
typename T,
typename U>
253 inline void set(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
254 const std::pair<T, U>& _desired)
256 set(&_atomic->first, _desired.first);
257 set(&_atomic->second, _desired.second);
260 template <
typename T,
typename U>
261 inline void set(std::pair<std::atomic<T>, std::atomic<U>>& _atomic,
262 const std::pair<T, U>& _desired)
264 set(&_atomic, _desired);
267 template <
typename T,
typename U>
268 inline void increment(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
269 const std::pair<T, U>& _increment)
271 increment(&_atomic->first, _increment.first);
272 increment(&_atomic->second, _increment.second);
275 template <
typename T,
typename U>
276 inline void decrement(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
277 const std::pair<T, U>& _decrement)
279 decrement(&_atomic->first, _decrement.first);
280 decrement(&_atomic->second, _decrement.second);
283 template <
typename T,
typename U>
284 inline void multiply(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
285 const std::pair<T, U>& _factor)
287 multiply(&_atomic->first, _factor.first);
288 multiply(&_atomic->second, _factor.second);
291 template <
typename T,
typename U>
292 inline void divide(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
293 const std::pair<T, U>& _factor)
295 divide(&_atomic->first, _factor.first);
296 divide(&_atomic->second, _factor.second);
301 template <
typename T,
typename U>
302 inline void set(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
303 const std::pair<std::atomic<T>, std::atomic<U>>& _desired)
305 set(&_atomic->first, _desired.first);
306 set(&_atomic->second, _desired.second);
309 template <
typename T,
typename U>
310 inline void set(std::pair<std::atomic<T>, std::atomic<U>>& _atomic,
311 const std::pair<std::atomic<T>, std::atomic<U>>& _desired)
313 set(&_atomic, _desired);
316 template <
typename T,
typename U>
317 inline void increment(
318 std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
319 const std::pair<std::atomic<T>, std::atomic<U>>& _increment)
321 increment(&_atomic->first, _increment.first);
322 increment(&_atomic->second, _increment.second);
325 template <
typename T,
typename U>
326 inline void decrement(
327 std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
328 const std::pair<std::atomic<T>, std::atomic<U>>& _decrement)
330 decrement(&_atomic->first, _decrement.first);
331 decrement(&_atomic->second, _decrement.second);
334 template <
typename T,
typename U>
335 inline void multiply(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
336 const std::pair<std::atomic<T>, std::atomic<U>>& _factor)
338 multiply(&_atomic->first, _factor.first);
339 multiply(&_atomic->second, _factor.second);
342 template <
typename T,
typename U>
343 inline void divide(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
344 const std::pair<std::atomic<T>, std::atomic<U>>& _factor)
346 divide(&_atomic->first, _factor.first);
347 divide(&_atomic->second, _factor.second);
352 template <
typename T>
353 inline T get(
const T& _non_atomic)
358 template <
typename T>
359 inline T get(
const T& _non_atomic, std::memory_order)
364 template <
typename T>
365 inline T get(
const std::atomic<T>& _atomic)
367 return _atomic.load();
370 template <
typename T>
371 inline T get(
const std::atomic<T>& _atomic, std::memory_order mem_odr)
373 return _atomic.load(mem_odr);
376 template <
typename T,
typename U>
377 inline std::pair<T, U> get(
378 const std::pair<std::atomic<T>, std::atomic<U>>& _atomic)
380 return std::pair<T, U>(get(_atomic.first), get(_atomic.second));
383 template <
typename T,
typename U>
384 inline std::pair<T, U> get(
385 const std::pair<std::atomic<T>, std::atomic<U>>& _atomic,
386 std::memory_order mem_odr)
388 return std::pair<T, U>(get(_atomic.first, mem_odr),
389 get(_atomic.second, mem_odr));
395 template <
typename _Tp_base,
typename _Tp_atom>
396 inline _Tp_base base(
const _Tp_atom& _atomic)