Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:06:46

0001 //FJSTARTHEADER
0002 // $Id$
0003 //
0004 // Copyright (c) 2014-2021, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
0005 //
0006 //----------------------------------------------------------------------
0007 // This file is part of FastJet.
0008 //
0009 //  FastJet is free software; you can redistribute it and/or modify
0010 //  it under the terms of the GNU General Public License as published by
0011 //  the Free Software Foundation; either version 2 of the License, or
0012 //  (at your option) any later version.
0013 //
0014 //  The algorithms that underlie FastJet have required considerable
0015 //  development. They are described in the original FastJet paper,
0016 //  hep-ph/0512210 and in the manual, arXiv:1111.6097. If you use
0017 //  FastJet as part of work towards a scientific publication, please
0018 //  quote the version you use and include a citation to the manual and
0019 //  optionally also to hep-ph/0512210.
0020 //
0021 //  FastJet is distributed in the hope that it will be useful,
0022 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
0023 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0024 //  GNU General Public License for more details.
0025 //
0026 //  You should have received a copy of the GNU General Public License
0027 //  along with FastJet. If not, see <http://www.gnu.org/licenses/>.
0028 //----------------------------------------------------------------------
0029 //FJENDHEADER
0030 
0031 #ifndef __FASTJET_THREAD_SAFETY_HELPERS_HH__
0032 #define __FASTJET_THREAD_SAFETY_HELPERS_HH__
0033 
0034 /// The code in this file is supposed to help writing code that will
0035 /// automatically provide thread-safe features when available and come
0036 /// revert back to "old/standard" C++ if thread-safety is not switched
0037 /// on
0038 ///
0039 ///\TODO fix doxygen comments (declare things as internal; make sure
0040 /// doxygen doc is not duplicate --- if necessary, keep only doxygen
0041 /// comments in the thread-safe versions)
0042 
0043 #include "fastjet/internal/base.hh"
0044 #include "fastjet/config.h"
0045 #include <limits>
0046 
0047 #ifdef FASTJET_HAVE_LIMITED_THREAD_SAFETY
0048 
0049 // introduces a few tools in CXX11 that we'll use in some FJ classes
0050 #include <atomic>
0051 
0052 FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
0053 
0054 namespace thread_safety_helpers{
0055 
0056   //----------------------------------------------------------------------
0057   /// \if internal_doc
0058   /// \class AtomicCounter
0059   ///
0060   /// provides a thread-safe counter which can only step one unit at a time
0061   /// and has overflow protection
0062   /// \endif
0063   template<typename T>
0064   class AtomicCounter{
0065   public:
0066     /// default ctor
0067     AtomicCounter() : _count{0}{}
0068 
0069     /// ctor with initialisation
0070     AtomicCounter(const T &count) : _count{count}{}
0071 
0072     /// copy ctor (works around the deleted copy in atomic, see
0073     /// e.g. http://stackoverflow.com/questions/19883092/error-implicitly-deleted-because-the-default-definition-would-be-ill-formed-ve)
0074     AtomicCounter(const AtomicCounter &other) : _count{other._count.load()}{}
0075 
0076     /// for a more friendly usage, overload the type cast to the
0077     /// base template type
0078     operator T() const{ return _count.load();}
0079 
0080     /// get the count
0081     T get() const{ return _count.load();}
0082     
0083     /// set the counter to a given value
0084     void set(const T new_value){
0085       _count.store(new_value);
0086     }
0087 
0088     /// step the counter and return the count just before it was stepped
0089     ///
0090     /// Q: can we declare this as T && ...?
0091     T step(){
0092       // another thread could be upadting this at the same time, so extra
0093       // care is needed.
0094       //
0095       // Recall that the compare_exchange_strong will return true if the
0096       // exchange has been done. Otherwise, it means that the count
0097       // changed in the meantime, so we try again. Also, since when it
0098       // "fails" compare_exchange_strong loads the count of *this in
0099       // expected, count does not need to be re-read in the loop!
0100       //
0101       // Note that at the end of this procedure, count will countain the
0102       // number of times this warning occured just before this
0103       // occurence. It can thus be used to see if it needs to be printed
0104       // out
0105       //
0106       // Note also that compared to the apparently simpler fetch_add,
0107       // this method also avoids overflows
0108       T count = _count;
0109       while (_count < std::numeric_limits<T>::max()
0110              && !(_count.compare_exchange_strong(count, count+1)));
0111       return count;
0112     }
0113 
0114     /// override the ++ operator
0115     /// prefix version
0116     inline T operator++(){
0117       return step()+1;
0118     }
0119 
0120     /// override the ++ operator
0121     /// postfix version
0122     inline T operator++(int){
0123       return step();
0124     }
0125 
0126   private:
0127     std::atomic<T> _count;  ///< the actual count
0128   };
0129   
0130   //----------------------------------------------------------------------
0131   /// \if internal_doc
0132   /// \class FirstTimeTrue
0133   /// provides an object wich will return "true" the first time () is
0134   /// called and false afterwards
0135   /// \endif
0136   class FirstTimeTrue{
0137   public:
0138     FirstTimeTrue(): _first_time{true}{}
0139     // explicit copy ctor (this class contains atimoc vars)
0140     FirstTimeTrue(const FirstTimeTrue &other) : _first_time{other._first_time.load()}{}
0141     bool operator()(){
0142       // Thread-safety note:
0143       //   the construct
0144       //      if (!_first_time) {return;}
0145       //      _first_time = false;
0146       //   is dangerous because the test can be passed by a second thread
0147       //   before the first one has set it to false. Use atomic exchange
0148       //   to handle this better
0149       bool expected = true;
0150       // this behaves as follows: if we have the expected value (true),
0151       // set _first_time to the desired (false) and return
0152       // true. Otherwise, do nothing and return false
0153       //
0154       // Note that since we are not using the "expected" value
0155       // afterwards, we can use a relaxed memory ordering if the next
0156       // call returns false
0157       return _first_time.compare_exchange_strong(expected, false,
0158                                                  std::memory_order_seq_cst,
0159                                                  std::memory_order_relaxed);
0160     }
0161   private:
0162     std::atomic<bool> _first_time;
0163   };
0164 
0165 } // namespace thread_safety_helpers
0166 
0167 FASTJET_END_NAMESPACE
0168 
0169 #else  // FJ wo thread-safety features
0170 
0171 FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
0172 
0173 namespace thread_safety_helpers{
0174   //----------------------------------------------------------------------
0175   /// \class AtomicCounter
0176   ///
0177   /// (would) provides a thread-safe counter (with CXX11 features)
0178   template<typename T>
0179   class AtomicCounter{
0180   public:
0181     /// default ctor
0182     AtomicCounter() : _count(0){}
0183 
0184     /// ctor with initialisation
0185     AtomicCounter(const T &count) : _count(count){}
0186 
0187     /// copy ctor
0188     AtomicCounter(const AtomicCounter &other) : _count(other._count){}
0189 
0190     /// for a more friendly usage, overload the type cast
0191     ///
0192     /// This will (likely) allow a transparent usage w or wo C++11
0193     /// features enabled
0194     operator T() const{ return _count;}
0195        
0196     /// get the count
0197     T get() const{ return _count;}
0198 
0199     /// set the counter to a given value
0200     void set(const T new_value){
0201       _count = new_value;
0202     }
0203 
0204     /// step the counter and return the value just before it was stepped
0205     T step(){
0206       unsigned int count = _count;
0207       if (_count < std::numeric_limits<T>::max()){ _count++; }
0208       return count;
0209     }
0210 
0211     /// override the ++ operator
0212     /// prefix version
0213     inline T operator++(){
0214       return step()+1;
0215     }
0216 
0217     /// override the ++ operator
0218     /// postfix version
0219     inline T operator++(int){
0220       return step();
0221     }
0222     
0223   private:
0224     T _count;  ///< the actual value
0225   };
0226 
0227   //----------------------------------------------------------------------
0228   /// \class FirstTimeTrue
0229   /// provides an object wich will return "true" the first time () is
0230   /// called and false afterwards
0231   class FirstTimeTrue{
0232   public:
0233     FirstTimeTrue(): _first_time(true){}
0234     bool operator()(){
0235       if (!_first_time) {return false;}
0236       _first_time = false;
0237       return true;
0238     }
0239   private:
0240     bool _first_time;
0241   };
0242 } // namespace thread_safety_helpers
0243 
0244 FASTJET_END_NAMESPACE
0245 
0246 
0247 
0248 #endif // FASTJET_HAVE_LIMITED_THREAD_SAFETY
0249 
0250 #endif // __FASTJET_THREAD_SAFETY_HELPERS_HH__