Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-23 09:22:29

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 /// \file parallel/ThreadsafeScorers/include/G4atomic_defines.hh
0027 /// \brief Definition of the G4atomic_defines class
0028 //
0029 //
0030 //
0031 //
0032 /// This is a functional class for G4atomic. The functions in this
0033 ///     file are not intended to be used outside of their implementation
0034 ///     in G4atomic.
0035 //
0036 //
0037 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0038 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0039 
0040 #ifndef G4atomic_defines_hh_
0041 #define G4atomic_defines_hh_
0042 
0043 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0044 
0045 #ifdef G4MULTITHREADED
0046 
0047 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0048 
0049 #  include <atomic>
0050 #  include <functional>
0051 
0052 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
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 }  // namespace details
0099 //------------------------------------------------------------------------//
0100 //  WITH ATOMIC TEMPLATE BASE TYPE AS SECOND PARAMETER
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 //  WITH ATOMICS AS SECOND PARAMETER
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   // details::do_fetch_and_store(_atomic, _desired);
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 //               STANDARD OVERLOAD                                        //
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 //               STL PAIR OVERLOAD                                        //
0220 //------------------------------------------------------------------------//
0221 //
0222 //------------------------------------------------------------------------//
0223 //  WITH ATOMIC TEMPLATE TYPE AS SECOND PARAMETER
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 //  WITH ATOMICS AS SECOND PARAMETER
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 // for plain old data (POD) and pairs (e.g. std::pair<atomic<T>, atomic<U>>)
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 }  // namespace atomics
0369 
0370 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0371 
0372 #endif  // G4MULTITHREADED
0373 
0374 #endif  // atomic_typedefs_hh_