Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:49:52

0001 #pragma once
0002 /**
0003 stimer.h
0004 ==========
0005 
0006 Usage::
0007 
0008     stimer* t = new stimer  ; 
0009     t->start(); 
0010     t->stop(); 
0011     double dt = t->duration(); // duration between start and stop 
0012 
0013 
0014     stimer* t = stimer::create() ; 
0015     double dt0 = t->lap() ;   // duration between the create and the lap call
0016     double dt1 = t->lap() ;   // duration between this call and the last 
0017 
0018 To present the EpochCount stamps, which now standardize on microseconds (millionths of a second) use::
0019 
0020     In [1]: np.array([1681470877922940,1681470881149639], dtype="datetime64[us]" )
0021     Out[1]: array(['2023-04-14T11:14:37.922940', '2023-04-14T11:14:41.149639'], dtype='datetime64[us]')
0022 
0023     In [7]: np.array([1681470877922940,1681470881149639], dtype=np.uint64).view("datetime64[us]")
0024     Out[7]: array(['2023-04-14T11:14:37.922940', '2023-04-14T11:14:41.149639'], dtype='datetime64[us]')
0025 
0026 Or without numpy::
0027 
0028     In [1]: from time import localtime, strftime
0029     In [2]: t = 1681470877922940
0030     In [3]: print(strftime('%Y-%m-%d %H:%M:%S',localtime(t/1000000)))
0031     2023-04-14 12:14:37   ## NB +1hr from BST  
0032 
0033 **/
0034 
0035 #include <cassert>
0036 #include <chrono>
0037 #include <thread>
0038 #include <cstring>
0039 #include <ctime>
0040 #include <iostream>
0041 #include <string>
0042 #include <cstdint>
0043 #include <sstream>
0044 
0045 struct stimer
0046 {
0047    typedef std::chrono::time_point<std::chrono::system_clock> TP ; 
0048    typedef std::chrono::duration<double> DT ; 
0049    enum { UNSET, STARTED, STOPPED } ; 
0050 
0051    static constexpr const char* UNSET_   = "UNSET  " ; 
0052    static constexpr const char* STARTED_ = "STARTED" ; 
0053    static constexpr const char* STOPPED_ = "STOPPED" ; 
0054    static constexpr const char* ERROR_   = "ERROR  " ; 
0055    static constexpr const char* FORMAT_ZERO_ = "FORMAT_ZERO             " ; 
0056    static const char* Status(int st) ; 
0057    static uint64_t EpochCountAsis(const std::chrono::time_point<std::chrono::system_clock>& t0 ); 
0058    static uint64_t EpochCount(const std::chrono::time_point<std::chrono::system_clock>& t0 ); // microseconds
0059    static uint64_t EpochCountNow() ;  // microseconds
0060    static std::chrono::time_point<std::chrono::system_clock> TimePoint( uint64_t epoch_count ); 
0061    static std::time_t ApproxTime(const std::chrono::time_point<std::chrono::system_clock>& t0 ); 
0062 
0063    static const char* Format(uint64_t epoch_count ); 
0064    static const char* Format(const std::chrono::time_point<std::chrono::system_clock>& t0 ); 
0065    static const char* Format(std::time_t tt ); 
0066 
0067    std::string desc() const ; 
0068 
0069    TP _start ; 
0070    TP _stop ; 
0071    int status = UNSET ; 
0072 
0073    uint64_t start_count() const ; 
0074    uint64_t stop_count() const ; 
0075 
0076 
0077    // higher level API
0078    static stimer* create() ; 
0079    double done(); 
0080    double lap(); 
0081 
0082    // low level API
0083    bool is_ready() const ; 
0084    bool is_started() const ; 
0085    bool is_stopped() const ; 
0086 
0087    void start(); 
0088    void stop(); 
0089    double duration() const ; 
0090 
0091    // for testing 
0092    static void sleep(int seconds) ; 
0093 };
0094 
0095 
0096 inline const char* stimer::Status(int st)
0097 {
0098     const char* str = nullptr ; 
0099     switch(st)
0100     {
0101         case UNSET: str = UNSET_     ; break ; 
0102         case STARTED: str = STARTED_ ; break ; 
0103         case STOPPED: str = STOPPED_ ; break ;
0104         default:      str = ERROR_   ; break ;  
0105     }
0106     return str ; 
0107 }
0108 
0109 inline uint64_t stimer::EpochCountAsis(const std::chrono::time_point<std::chrono::system_clock>& t0 )
0110 {
0111    return t0.time_since_epoch().count(); 
0112 }
0113 inline uint64_t stimer::EpochCount(const std::chrono::time_point<std::chrono::system_clock>& t0 )
0114 {
0115    return std::chrono::duration_cast<std::chrono::microseconds>(t0.time_since_epoch()).count() ;  
0116 } 
0117 inline uint64_t stimer::EpochCountNow()
0118 {
0119     std::chrono::time_point<std::chrono::system_clock> t0 = std::chrono::system_clock::now();
0120     return EpochCount(t0); 
0121 }
0122 
0123 inline std::chrono::time_point<std::chrono::system_clock> stimer::TimePoint( uint64_t epoch_count_microseconds )
0124 {
0125     /*
0126     using clock = std::chrono::system_clock ; 
0127     clock::duration dur(epoch_count) ; 
0128     clock::time_point tp(dur);
0129     */
0130     std::chrono::system_clock::time_point tp{std::chrono::microseconds{epoch_count_microseconds}};
0131     return tp ; 
0132 }
0133 
0134 
0135 inline std::time_t stimer::ApproxTime(const std::chrono::time_point<std::chrono::system_clock>& t0 )
0136 {
0137     //auto highResNow = std::chrono::system_clock::now();
0138     //auto systemNow = std::chrono::system_clock::now();
0139     //auto offset = std::chrono::duration_cast<std::chrono::system_clock::duration>( highResNow - t0 ); 
0140     //auto output = systemNow + offset  ;
0141     std::time_t tt =  std::chrono::system_clock::to_time_t( t0 );
0142     return tt ; 
0143 }
0144 inline const char* stimer::Format(uint64_t epoch_count )
0145 {
0146     std::chrono::time_point<std::chrono::system_clock> tp = TimePoint(epoch_count); 
0147     return Format(tp) ; 
0148 }
0149 inline const char* stimer::Format(const std::chrono::time_point<std::chrono::system_clock>& t0 )
0150 {
0151     return EpochCount(t0) == 0 ? FORMAT_ZERO_ : Format(ApproxTime(t0)) ; 
0152 }
0153 
0154 inline const char* stimer::Format( std::time_t tt )
0155 {
0156     std::tm* tm = std::localtime(&tt);
0157     char buffer[32];
0158     // Format: Mo, 15.06.2009 20:20:00
0159     std::strftime(buffer, 32, "%a, %d.%m.%Y %H:%M:%S", tm);  
0160     return strdup(buffer) ; 
0161 }
0162 inline std::string stimer::desc() const 
0163 {
0164     std::stringstream ss ; 
0165     ss << "stimer::desc"
0166        << " status " << Status(status)
0167        << " _start " << EpochCount(_start) 
0168        << " start "  << Format(_start) 
0169        << " _stop " << EpochCount(_stop) 
0170        << " stop "   << Format(_stop) 
0171        << " duration " << std::scientific << duration() 
0172        ; 
0173     std::string str = ss.str(); 
0174     return str ; 
0175 }
0176 
0177 inline uint64_t stimer::start_count() const { return EpochCount(_start) ; }
0178 inline uint64_t stimer::stop_count() const {  return EpochCount(_stop) ; }
0179 
0180 
0181 inline stimer* stimer::create()
0182 {
0183     stimer* t = new stimer ; 
0184     t->start(); 
0185     return t ; 
0186 }
0187 inline double stimer::done() 
0188 {
0189     stop(); 
0190     return duration(); 
0191 }
0192 inline double stimer::lap() 
0193 {
0194     stop(); 
0195     double dt = duration(); 
0196     start(); 
0197     return dt ; 
0198 }
0199 
0200 
0201 inline bool stimer::is_ready() const {   return status == UNSET || status == STOPPED ; }
0202 inline bool stimer::is_started() const { return status == STARTED ; }
0203 inline bool stimer::is_stopped() const { return status == STOPPED ; }
0204 
0205 inline void stimer::start()
0206 {
0207     if(!is_ready()) std::cerr << "stimer::start called when STARTED already ? " << desc() << std::endl ;  
0208     status = STARTED ; 
0209     _start = std::chrono::system_clock::now(); 
0210 } 
0211 inline void stimer::stop()
0212 {
0213     if(!is_started()) std::cerr << "stimer::stop called when not STARTED ? " << desc() << std::endl ;  
0214     status = STOPPED ; 
0215     _stop  = std::chrono::system_clock::now(); 
0216 } 
0217 inline double stimer::duration() const 
0218 {
0219     if(!is_stopped()) return -1. ;   
0220     DT _dt = _stop - _start ; 
0221     return _dt.count(); 
0222 }
0223 
0224 
0225 
0226 inline void stimer::sleep(int seconds) // static
0227 {
0228     std::chrono::seconds dura(seconds);
0229     std::this_thread::sleep_for( dura );
0230 }
0231 
0232 
0233 
0234 
0235 
0236 
0237 
0238