Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:57:31

0001 /***********************************************************************************\
0002 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
0003 *                                                                                   *
0004 * This software is distributed under the terms of the Apache version 2 licence,     *
0005 * copied verbatim in the file "LICENSE".                                            *
0006 *                                                                                   *
0007 * In applying this licence, CERN does not waive the privileges and immunities       *
0008 * granted to it by virtue of its status as an Intergovernmental Organization        *
0009 * or submit itself to any jurisdiction.                                             *
0010 \***********************************************************************************/
0011 #pragma once
0012 
0013 #include "Gaudi/Chrono/Counters.h"
0014 
0015 #include <atomic>
0016 #include <chrono>
0017 
0018 namespace Gaudi {
0019   namespace Timers {
0020     /**
0021      * A generic timer based on std::chrono and Gaudi::Accumulators
0022      *
0023      * The timer is templated with a std::chrono compatible clock and the Unit
0024      * of precision (ms, us, ...). It accumulates all time measurements in a
0025      * Gaudi::Accumulators::StatCounter. A time measurement is done via the RAII helper
0026      * class created by calling operator().
0027      *
0028      * Usually one would use one of the predefined Timer types from Gaudi/Timers.h:
0029      *
0030      * @code
0031      *   // .h
0032      *   Gaudi::Timer m_timer;
0033      *
0034      *   // .cpp
0035      *   {
0036      *     auto timeit = m_timer();
0037      *     // code to be timed
0038      *   }
0039      *   info() << m_timer.stats() << endmsg;
0040      * @endcode
0041      */
0042     template <typename Clock, typename Unit>
0043     class GenericTimer {
0044     public:
0045       /// Type of Counter used for accumulating time measurements
0046       typedef Gaudi::Accumulators::StatCounter<Unit> Stats_t;
0047 
0048       /**
0049        * A scoped timer that starts/stops on con/de-struction
0050        */
0051       class ScopeTimer {
0052       public:
0053         /// Start Scoped timer accumulating into stat
0054         ScopeTimer( Stats_t& stat ) : m_stats( stat ), m_t0( Clock::now() ) {}
0055 
0056         /// Destructor stopping timer
0057         ~ScopeTimer() { stop(); }
0058 
0059         /// Return the elapsed time without stopping the timer
0060         /// @return std::chrono::duration<Unit>
0061         auto elapsed() const {
0062           // Fenced according to https://codereview.stackexchange.com/q/196245
0063           std::atomic_thread_fence( std::memory_order_relaxed );
0064           auto dt = Clock::now() - m_t0;
0065           std::atomic_thread_fence( std::memory_order_relaxed );
0066           return std::chrono::duration_cast<Unit>( dt );
0067         }
0068 
0069       private:
0070         /// Stop the timer, accumulate elapsed time and return current measurement
0071         void stop() const { m_stats += elapsed(); }
0072 
0073         Stats_t&                   m_stats; ///< reference to statistics counter
0074         typename Clock::time_point m_t0;    ///< start time of timer
0075       };
0076 
0077       /// Default constructor
0078       GenericTimer() = default;
0079 
0080       /// Constructor attaching the statistics counter to an owner
0081       template <class OWNER>
0082       GenericTimer( OWNER* o, const std::string& name ) {
0083         o->declareCounter( name, std::string{ "timer:" } + typeid( Unit::rep ).name(), m_stats );
0084       }
0085 
0086       /// No copy
0087       GenericTimer( const GenericTimer& ) = delete;
0088 
0089       /// Create (and start) a ScopeTimer
0090       [[nodiscard]] auto operator()() const { return ScopeTimer( m_stats ); }
0091 
0092       /// Return accumulated timing statistics
0093       const Stats_t& stats() const { return m_stats; }
0094 
0095     private:
0096       mutable Stats_t m_stats; ///< statistics counter
0097     };
0098 
0099   } // namespace Timers
0100 } // namespace Gaudi