File indexing completed on 2025-02-23 09:22:29
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #ifndef G4atomic_defines_hh_
0041 #define G4atomic_defines_hh_
0042
0043
0044
0045 #ifdef G4MULTITHREADED
0046
0047
0048
0049 # include <atomic>
0050 # include <functional>
0051
0052
0053
0054 namespace atomics
0055 {
0056
0057 namespace details
0058 {
0059
0060 template<typename _Tp>
0061 using OpFunction = std::function<_Tp(const _Tp&, const _Tp&)>;
0062
0063 template<typename _Tp>
0064 inline void do_fetch_and_store(std::atomic<_Tp>* _atomic, const _Tp& _value,
0065 std::memory_order mem_odr)
0066 {
0067 _atomic->store(_value, mem_odr);
0068 }
0069
0070 template<typename _Tp>
0071 inline void do_fetch_and_store(std::atomic<_Tp>* _atomic, const std::atomic<_Tp>& _value,
0072 std::memory_order mem_odr)
0073 {
0074 _atomic->store(_value.load(), mem_odr);
0075 }
0076
0077 template<typename _Tp>
0078 inline void do_compare_and_swap(std::atomic<_Tp>* _atomic, const _Tp& _value,
0079 const OpFunction<_Tp>& _operator, std::memory_order mem_odr)
0080 {
0081 _Tp _expected = _Tp();
0082 do {
0083 _expected = _atomic->load();
0084 } while (!(_atomic->compare_exchange_weak(_expected, _operator(_expected, _value), mem_odr)));
0085 }
0086
0087 template<typename _Tp>
0088 inline void do_compare_and_swap(std::atomic<_Tp>* _atomic, const std::atomic<_Tp>& _atomic_value,
0089 const OpFunction<_Tp>& _operator, std::memory_order mem_odr)
0090 {
0091 _Tp _expected = _Tp();
0092 do {
0093 _expected = _atomic->load();
0094 } while (!(_atomic->compare_exchange_weak(_expected, _operator(_expected, _atomic_value.load()),
0095 mem_odr)));
0096 }
0097
0098 }
0099
0100
0101
0102 template<typename T>
0103 inline void set(std::atomic<T>* _atomic, const T& _desired,
0104 std::memory_order mem_odr = std::memory_order_seq_cst)
0105 {
0106 details::do_compare_and_swap(
0107 _atomic, _desired, details::OpFunction<T>([](const T&, const T& y) { return y; }), mem_odr);
0108 }
0109
0110 template<typename T>
0111 inline void set(std::atomic<T>& _atomic, const T& _desired,
0112 std::memory_order mem_odr = std::memory_order_seq_cst)
0113 {
0114 set(&_atomic, _desired, mem_odr);
0115 }
0116
0117 template<typename T>
0118 inline void increment(std::atomic<T>* _atomic, const T& _increment, std::memory_order mem_odr)
0119 {
0120 details::do_compare_and_swap(_atomic, _increment,
0121 details::OpFunction<T>([](const T& x, const T& y) { return x + y; }),
0122 mem_odr);
0123 }
0124
0125 template<typename T>
0126 inline void decrement(std::atomic<T>* _atomic, const T& _decrement, std::memory_order mem_odr)
0127 {
0128 details::do_compare_and_swap(_atomic, _decrement,
0129 details::OpFunction<T>([](const T& x, const T& y) { return x - y; }),
0130 mem_odr);
0131 }
0132
0133 template<typename T>
0134 inline void multiply(std::atomic<T>* _atomic, const T& _factor, std::memory_order mem_odr)
0135 {
0136 details::do_compare_and_swap(_atomic, _factor,
0137 details::OpFunction<T>([](const T& x, const T& y) { return x * y; }),
0138 mem_odr);
0139 }
0140
0141 template<typename T>
0142 inline void divide(std::atomic<T>* _atomic, const T& _factor, std::memory_order mem_odr)
0143 {
0144 details::do_compare_and_swap(_atomic, _factor,
0145 details::OpFunction<T>([](const T& x, const T& y) { return x / y; }),
0146 mem_odr);
0147 }
0148
0149
0150
0151 template<typename T>
0152 inline void set(std::atomic<T>* _atomic, const std::atomic<T>& _atomic_desired,
0153 std::memory_order mem_odr = std::memory_order_seq_cst)
0154 {
0155
0156 details::do_compare_and_swap(_atomic, _atomic_desired,
0157 details::OpFunction<T>([](const T&, const T& y) { return y; }),
0158 mem_odr);
0159 }
0160
0161 template<typename T>
0162 inline void set(std::atomic<T>& _atomic, const std::atomic<T>& _atomic_desired,
0163 std::memory_order mem_odr)
0164 {
0165 set(&_atomic, _atomic_desired, mem_odr);
0166 }
0167
0168 template<typename T>
0169 inline void increment(std::atomic<T>* _atomic, const std::atomic<T>& _atomic_increment,
0170 std::memory_order mem_odr)
0171 {
0172 details::do_compare_and_swap(_atomic, _atomic_increment,
0173 details::OpFunction<T>([](const T& x, const T& y) { return x + y; }),
0174 mem_odr);
0175 }
0176
0177 template<typename T>
0178 inline void decrement(std::atomic<T>* _atomic, const std::atomic<T>& _atomic_decrement,
0179 std::memory_order mem_odr)
0180 {
0181 details::do_compare_and_swap(_atomic, _atomic_decrement,
0182 details::OpFunction<T>([](const T& x, const T& y) { return x - y; }),
0183 mem_odr);
0184 }
0185
0186 template<typename T>
0187 inline void multiply(std::atomic<T>* _atomic, const std::atomic<T>& _atomic_factor,
0188 std::memory_order mem_odr)
0189 {
0190 details::do_compare_and_swap(_atomic, _atomic_factor,
0191 details::OpFunction<T>([](const T& x, const T& y) { return x * y; }),
0192 mem_odr);
0193 }
0194
0195 template<typename T>
0196 inline void divide(std::atomic<T>* _atomic, const std::atomic<T>& _atomic_factor,
0197 std::memory_order mem_odr)
0198 {
0199 details::do_compare_and_swap(_atomic, _atomic_factor,
0200 details::OpFunction<T>([](const T& x, const T& y) { return x / y; }),
0201 mem_odr);
0202 }
0203
0204
0205
0206
0207 template<typename T>
0208 inline void set(T* _non_atomic, const T& _desired)
0209 {
0210 *_non_atomic = _desired;
0211 }
0212
0213 template<typename T>
0214 inline void set(T& _non_atomic, const T& _desired)
0215 {
0216 set(&_non_atomic, _desired);
0217 }
0218
0219
0220
0221
0222
0223
0224
0225 template<typename T, typename U>
0226 inline void set(std::pair<std::atomic<T>, std::atomic<U>>* _atomic, const std::pair<T, U>& _desired)
0227 {
0228 set(&_atomic->first, _desired.first);
0229 set(&_atomic->second, _desired.second);
0230 }
0231
0232 template<typename T, typename U>
0233 inline void set(std::pair<std::atomic<T>, std::atomic<U>>& _atomic, const std::pair<T, U>& _desired)
0234 {
0235 set(&_atomic, _desired);
0236 }
0237
0238 template<typename T, typename U>
0239 inline void increment(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
0240 const std::pair<T, U>& _increment)
0241 {
0242 increment(&_atomic->first, _increment.first);
0243 increment(&_atomic->second, _increment.second);
0244 }
0245
0246 template<typename T, typename U>
0247 inline void decrement(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
0248 const std::pair<T, U>& _decrement)
0249 {
0250 decrement(&_atomic->first, _decrement.first);
0251 decrement(&_atomic->second, _decrement.second);
0252 }
0253
0254 template<typename T, typename U>
0255 inline void multiply(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
0256 const std::pair<T, U>& _factor)
0257 {
0258 multiply(&_atomic->first, _factor.first);
0259 multiply(&_atomic->second, _factor.second);
0260 }
0261
0262 template<typename T, typename U>
0263 inline void divide(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
0264 const std::pair<T, U>& _factor)
0265 {
0266 divide(&_atomic->first, _factor.first);
0267 divide(&_atomic->second, _factor.second);
0268 }
0269
0270
0271
0272 template<typename T, typename U>
0273 inline void set(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
0274 const std::pair<std::atomic<T>, std::atomic<U>>& _desired)
0275 {
0276 set(&_atomic->first, _desired.first);
0277 set(&_atomic->second, _desired.second);
0278 }
0279
0280 template<typename T, typename U>
0281 inline void set(std::pair<std::atomic<T>, std::atomic<U>>& _atomic,
0282 const std::pair<std::atomic<T>, std::atomic<U>>& _desired)
0283 {
0284 set(&_atomic, _desired);
0285 }
0286
0287 template<typename T, typename U>
0288 inline void increment(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
0289 const std::pair<std::atomic<T>, std::atomic<U>>& _increment)
0290 {
0291 increment(&_atomic->first, _increment.first);
0292 increment(&_atomic->second, _increment.second);
0293 }
0294
0295 template<typename T, typename U>
0296 inline void decrement(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
0297 const std::pair<std::atomic<T>, std::atomic<U>>& _decrement)
0298 {
0299 decrement(&_atomic->first, _decrement.first);
0300 decrement(&_atomic->second, _decrement.second);
0301 }
0302
0303 template<typename T, typename U>
0304 inline void multiply(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
0305 const std::pair<std::atomic<T>, std::atomic<U>>& _factor)
0306 {
0307 multiply(&_atomic->first, _factor.first);
0308 multiply(&_atomic->second, _factor.second);
0309 }
0310
0311 template<typename T, typename U>
0312 inline void divide(std::pair<std::atomic<T>, std::atomic<U>>* _atomic,
0313 const std::pair<std::atomic<T>, std::atomic<U>>& _factor)
0314 {
0315 divide(&_atomic->first, _factor.first);
0316 divide(&_atomic->second, _factor.second);
0317 }
0318
0319
0320
0321 template<typename T>
0322 inline T get(const T& _non_atomic)
0323 {
0324 return _non_atomic;
0325 }
0326
0327 template<typename T>
0328 inline T get(const T& _non_atomic, std::memory_order)
0329 {
0330 return _non_atomic;
0331 }
0332
0333 template<typename T>
0334 inline T get(const std::atomic<T>& _atomic)
0335 {
0336 return _atomic.load();
0337 }
0338
0339 template<typename T>
0340 inline T get(const std::atomic<T>& _atomic, std::memory_order mem_odr)
0341 {
0342 return _atomic.load(mem_odr);
0343 }
0344
0345 template<typename T, typename U>
0346 inline std::pair<T, U> get(const std::pair<std::atomic<T>, std::atomic<U>>& _atomic)
0347 {
0348 return std::pair<T, U>(get(_atomic.first), get(_atomic.second));
0349 }
0350
0351 template<typename T, typename U>
0352 inline std::pair<T, U> get(const std::pair<std::atomic<T>, std::atomic<U>>& _atomic,
0353 std::memory_order mem_odr)
0354 {
0355 return std::pair<T, U>(get(_atomic.first, mem_odr), get(_atomic.second, mem_odr));
0356 }
0357
0358
0359
0360
0361 template<typename _Tp_base, typename _Tp_atom>
0362 inline _Tp_base base(const _Tp_atom& _atomic)
0363 {
0364 return get(_atomic);
0365 }
0366
0367
0368 }
0369
0370
0371
0372 #endif
0373
0374 #endif