Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /geant4/examples/extended/parallel/ThreadsafeScorers/include/G4atomic_defines.hh was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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