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.hh
0027 /// \brief Definition of the G4atomic class
0028 //
0029 //
0030 //
0031 //
0032 /// This is an friendly implementation of the STL atomic class.
0033 ///     This class has the same interface as the STL atomic but can be used
0034 ///     in an extremely similar fashion to plain old data (POD) types.
0035 ///     In other words, the copy constructor and assignment operators are
0036 ///     defined, and a load() does not need to be called to get the POD
0037 ///     value.
0038 ///
0039 /// IMPORTANT: Care must be taken when using this class as a RHS term.
0040 ///     The best use case scenario for this class is as a LHS term that is
0041 ///     only used as a RHS term outside of the multithreaded operations on it.
0042 ///
0043 /// FOR EXAMPLE:
0044 ///     Proper use:
0045 ///         Goal: sum energy deposited in run
0046 ///         Impl: Is a member variable of derived
0047 ///                   G4VUserActionInitialization (of which there will
0048 ///                   always be just one instance). Accumulate
0049 ///                   thread-local energy deposit into EventAction,
0050 ///                   add to ActionInit at end of event, print sum
0051 ///                   on master EndOfRunAction
0052 ///         Why: the sum is only a LHS term
0053 ///     Improper use:
0054 ///         Goal: compute error during event processing
0055 ///         Impl: sum += x; sum_sq += x*x; counts++;
0056 ///               error = sqrt(sum_sq/(sum*sum) - 1/counts;
0057 ///               (where sum, sum_sq, counts are G4atomics)
0058 ///         Why: This will work but error can/will be wrong when
0059 ///              sum, sum_sq, and counts are updated by another thread
0060 ///              while error is being calculated, i.e. they are used as
0061 ///              RHS terms
0062 //
0063 //
0064 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0065 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0066 
0067 #ifndef G4atomic_hh_
0068 #define G4atomic_hh_
0069 
0070 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0071 
0072 #ifdef G4MULTITHREADED
0073 
0074 #  include "G4atomic_defines.hh"
0075 
0076 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0077 
0078 template<typename _Tp>
0079 class G4atomic
0080 {
0081   public:
0082     typedef typename std::atomic<_Tp> base_type;
0083     typedef _Tp value_type;
0084 
0085   private:
0086     using mem_ord = std::memory_order;
0087 
0088   public:
0089     // constructors
0090     explicit G4atomic(mem_ord mo = std::memory_order_acq_rel) : fMemOrder(mo)
0091     {
0092       atomics::set(&fvalue, value_type());
0093     }
0094 
0095     explicit G4atomic(const value_type& _init, mem_ord mo = std::memory_order_acq_rel)
0096       : fMemOrder(mo)
0097     {
0098       atomics::set(&fvalue, _init);
0099     }
0100 
0101     // copy-constructor from pure C++11 atomic
0102     explicit G4atomic(const base_type& rhs, mem_ord mo = std::memory_order_acq_rel) : fMemOrder(mo)
0103     {
0104       atomics::set(&fvalue, rhs);
0105     }
0106 
0107     // copy-constructor
0108     explicit G4atomic(const G4atomic& rhs) : fMemOrder(rhs.fMemOrder)
0109     {
0110       atomics::set(&fvalue, rhs.base());
0111     }
0112 
0113     // assignment operators
0114     G4atomic& operator=(const G4atomic& rhs)
0115     {
0116       if (this != &rhs) atomics::set(&fvalue, rhs.fvalue);
0117       return *this;
0118     }
0119 
0120     G4atomic& operator=(const value_type& rhs)
0121     {
0122       atomics::set(&fvalue, rhs);
0123       return *this;
0124     }
0125 
0126     G4atomic& operator=(const base_type& rhs)
0127     {
0128       atomics::set(&fvalue, rhs);
0129       return *this;
0130     }
0131 
0132     // destructor
0133     ~G4atomic() { fvalue.~base_type(); }
0134 
0135     // base version
0136     base_type& base() { return fvalue; }
0137     const base_type& base() const { return fvalue; }
0138     base_type& base() volatile { return fvalue; }
0139     const base_type& base() const volatile { return fvalue; }
0140 
0141     // check if atomic is lock-free
0142     bool is_lock_free() const { return fvalue.is_lock_free(); }
0143     bool is_lock_free() const volatile { return fvalue.is_lock_free(); }
0144 
0145     // store functions
0146     void store(_Tp _desired, mem_ord mo = std::memory_order_seq_cst)
0147     {
0148       atomics::set(fvalue, _desired, mo);
0149     }
0150     void store(_Tp _desired, mem_ord mo = std::memory_order_seq_cst) volatile
0151     {
0152       atomics::set(fvalue, _desired, mo);
0153     }
0154 
0155     // load functions
0156     _Tp load(mem_ord mo = std::memory_order_seq_cst) const { return atomics::get(fvalue, mo); }
0157     _Tp load(mem_ord mo = std::memory_order_seq_cst) const volatile
0158     {
0159       return atomics::get(fvalue, mo);
0160     }
0161 
0162     // implicit conversion functions
0163     operator _Tp() const { return this->load(); }
0164     operator _Tp() const volatile { return this->load(); }
0165 
0166     operator base_type&() const { return fvalue; }
0167 
0168     // compare-and-swap functions
0169     bool compare_exchange_weak(_Tp& _expected, _Tp _desired, mem_ord _success, mem_ord _failure)
0170     {
0171       return fvalue.compare_exchange_weak(_expected, _desired, _success, _failure);
0172     }
0173     bool compare_exchange_weak(_Tp& _expected, _Tp _desired, mem_ord _success,
0174                                mem_ord _failure) volatile
0175     {
0176       return fvalue.compare_exchange_weak(_expected, _desired, _success, _failure);
0177     }
0178 
0179     bool compare_exchange_weak(_Tp& _expected, _Tp _desired, mem_ord _order)
0180     {
0181       return fvalue.compare_exchange_weak(_expected, _desired, _order);
0182     }
0183     bool compare_exchange_weak(_Tp& _expected, _Tp _desired, mem_ord _order) volatile
0184     {
0185       return fvalue.compare_exchange_weak(_expected, _desired, _order);
0186     }
0187 
0188     bool compare_exchange_strong(_Tp& _expected, _Tp _desired, mem_ord _success, mem_ord _failure)
0189     {
0190       return fvalue.compare_exchange_weak(_expected, _desired, _success, _failure);
0191     }
0192     bool compare_exchange_strong(_Tp& _expected, _Tp _desired, mem_ord _success,
0193                                  mem_ord _failure) volatile
0194     {
0195       return fvalue.compare_exchange_weak(_expected, _desired, _success, _failure);
0196     }
0197 
0198     bool compare_exchange_strong(_Tp& _expected, _Tp _desired, mem_ord _order)
0199     {
0200       return fvalue.compare_exchange_weak(_expected, _desired, _order);
0201     }
0202     bool compare_exchange_strong(_Tp& _expected, _Tp _desired, mem_ord _order) volatile
0203     {
0204       return fvalue.compare_exchange_weak(_expected, _desired, _order);
0205     }
0206 
0207     // value_type operators
0208     G4atomic& operator+=(const value_type& rhs)
0209     {
0210       atomics::increment(&fvalue, rhs, fMemOrder);
0211       return *this;
0212     }
0213     G4atomic& operator-=(const value_type& rhs)
0214     {
0215       atomics::decrement(&fvalue, rhs, fMemOrder);
0216       return *this;
0217     }
0218     G4atomic& operator*=(const value_type& rhs)
0219     {
0220       atomics::multiply(&fvalue, rhs, fMemOrder);
0221       return *this;
0222     }
0223     G4atomic& operator/=(const value_type& rhs)
0224     {
0225       atomics::divide(&fvalue, rhs, fMemOrder);
0226       return *this;
0227     }
0228 
0229     // atomic operators
0230     G4atomic& operator+=(const G4atomic& rhs)
0231     {
0232       atomics::increment(&fvalue, rhs.fvalue);
0233       return *this;
0234     }
0235     G4atomic& operator-=(const G4atomic& rhs)
0236     {
0237       atomics::decrement(&fvalue, rhs.fvalue);
0238       return *this;
0239     }
0240     G4atomic& operator*=(const G4atomic& rhs)
0241     {
0242       atomics::multiply(&fvalue, rhs.fvalue);
0243       return *this;
0244     }
0245     G4atomic& operator/=(const G4atomic& rhs)
0246     {
0247       atomics::divide(&fvalue, rhs.fvalue);
0248       return *this;
0249     }
0250 
0251     G4atomic& operator+=(const G4atomic& rhs) volatile
0252     {
0253       atomics::increment(&fvalue, rhs.fvalue);
0254       return *this;
0255     }
0256     G4atomic& operator-=(const G4atomic& rhs) volatile
0257     {
0258       atomics::decrement(&fvalue, rhs.fvalue);
0259       return *this;
0260     }
0261     G4atomic& operator*=(const G4atomic& rhs) volatile
0262     {
0263       atomics::multiply(&fvalue, rhs.fvalue);
0264       return *this;
0265     }
0266     G4atomic& operator/=(const G4atomic& rhs) volatile
0267     {
0268       atomics::divide(&fvalue, rhs.fvalue);
0269       return *this;
0270     }
0271 
0272     // STL atomic operators
0273     G4atomic& operator+=(const std::atomic<_Tp>& rhs)
0274     {
0275       atomics::increment(&fvalue, rhs, fMemOrder);
0276       return *this;
0277     }
0278     G4atomic& operator-=(const std::atomic<_Tp>& rhs)
0279     {
0280       atomics::decrement(&fvalue, rhs, fMemOrder);
0281       return *this;
0282     }
0283     G4atomic& operator*=(const std::atomic<_Tp>& rhs)
0284     {
0285       atomics::multiply(&fvalue, rhs, fMemOrder);
0286       return *this;
0287     }
0288     G4atomic& operator/=(const std::atomic<_Tp>& rhs)
0289     {
0290       atomics::divide(&fvalue, rhs, fMemOrder);
0291       return *this;
0292     }
0293 
0294     G4atomic& operator+=(const std::atomic<_Tp>& rhs) volatile
0295     {
0296       atomics::increment(&fvalue, rhs, fMemOrder);
0297       return *this;
0298     }
0299     G4atomic& operator-=(const std::atomic<_Tp>& rhs) volatile
0300     {
0301       atomics::decrement(&fvalue, rhs, fMemOrder);
0302       return *this;
0303     }
0304     G4atomic& operator*=(const std::atomic<_Tp>& rhs) volatile
0305     {
0306       atomics::multiply(&fvalue, rhs, fMemOrder);
0307       return *this;
0308     }
0309     G4atomic& operator/=(const std::atomic<_Tp>& rhs) volatile
0310     {
0311       atomics::divide(&fvalue, rhs, fMemOrder);
0312       return *this;
0313     }
0314 
0315     // increment operators
0316     value_type operator++()
0317     {
0318       value_type _tmp = ++fvalue;
0319       return _tmp;
0320     }
0321     value_type operator++(int)
0322     {
0323       value_type _tmp = fvalue++;
0324       return _tmp;
0325     }
0326 
0327     value_type operator--()
0328     {
0329       value_type _tmp = --fvalue;
0330       return _tmp;
0331     }
0332     value_type operator--(int)
0333     {
0334       value_type _tmp = fvalue--;
0335       return _tmp;
0336     }
0337 
0338   protected:
0339     base_type fvalue;
0340     mem_ord fMemOrder;
0341 };
0342 
0343 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0344 
0345 #else  // ! G4MULTITHREADED
0346 
0347 template<typename _Tp>
0348 using G4atomic = _Tp;
0349 
0350 #endif  // G4MULTITHREADED
0351 
0352 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0353 
0354 #endif  // G4atomic_hh_