Home | History | Annotate | Download | only in source
      1 //===-- DNBTimer.h ----------------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  Created by Greg Clayton on 12/13/07.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef __DNBTimer_h__
     15 #define __DNBTimer_h__
     16 
     17 #include <sys/time.h>
     18 #include <stdint.h>
     19 #include <memory>
     20 #include "DNBDefs.h"
     21 #include "PThreadMutex.h"
     22 
     23 class DNBTimer
     24 {
     25 public:
     26     //------------------------------------------------------------------
     27     // Constructors and Destructors
     28     //------------------------------------------------------------------
     29     DNBTimer (bool threadSafe) :
     30             m_mutexAP()
     31         {
     32             if (threadSafe)
     33                 m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
     34             Reset();
     35         }
     36 
     37     DNBTimer (const DNBTimer& rhs) :
     38             m_mutexAP()
     39         {
     40             // Create a new mutex to make this timer thread safe as well if
     41             // the timer we are copying is thread safe
     42             if (rhs.IsThreadSafe())
     43                 m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
     44             m_timeval = rhs.m_timeval;
     45         }
     46 
     47     DNBTimer& operator= (const DNBTimer& rhs)
     48         {
     49             // Create a new mutex to make this timer thread safe as well if
     50             // the timer we are copying is thread safe
     51             if (rhs.IsThreadSafe())
     52                 m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
     53             m_timeval = rhs.m_timeval;
     54             return *this;
     55         }
     56 
     57     ~DNBTimer ()
     58         {
     59         }
     60 
     61         bool
     62         IsThreadSafe() const
     63         {
     64             return m_mutexAP.get() != NULL;
     65         }
     66         //------------------------------------------------------------------
     67         // Reset the time value to now
     68         //------------------------------------------------------------------
     69         void
     70         Reset ()
     71         {
     72             PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get());
     73             gettimeofday (&m_timeval, NULL);
     74         }
     75         //------------------------------------------------------------------
     76         // Get the total mircoseconds since Jan 1, 1970
     77         //------------------------------------------------------------------
     78         uint64_t
     79         TotalMicroSeconds () const
     80         {
     81             PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get());
     82             return (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec;
     83         }
     84 
     85         void
     86         GetTime (uint32_t& sec, uint32_t& usec) const
     87         {
     88             PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get());
     89             sec = m_timeval.tv_sec;
     90             usec = m_timeval.tv_usec;
     91         }
     92         //------------------------------------------------------------------
     93         // Return the number of microseconds elapsed between now and the
     94         // m_timeval
     95         //------------------------------------------------------------------
     96         uint64_t
     97         ElapsedMicroSeconds (bool update)
     98         {
     99             PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get());
    100             struct timeval now;
    101             gettimeofday (&now, NULL);
    102             uint64_t now_usec = (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec;
    103             uint64_t this_usec = (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec;
    104             uint64_t elapsed = now_usec - this_usec;
    105             // Update the timer time value if requeseted
    106             if (update)
    107                 m_timeval = now;
    108             return elapsed;
    109         }
    110 
    111         static uint64_t GetTimeOfDay()
    112         {
    113             struct timeval now;
    114             gettimeofday (&now, NULL);
    115             uint64_t now_usec = (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec;
    116             return now_usec;
    117         }
    118 
    119         static void OffsetTimeOfDay (struct timespec* ts, __darwin_time_t sec_offset = 0, long nsec_offset = 0)
    120         {
    121             if (ts == NULL)
    122                 return;
    123             // Get the current time in a timeval structure
    124             struct timeval now;
    125             gettimeofday (&now, NULL);
    126             // Morph it into a timespec
    127             TIMEVAL_TO_TIMESPEC(&now, ts);
    128             // Offset the timespec if requested
    129             if (sec_offset != 0 || nsec_offset != 0)
    130             {
    131                 // Offset the nano seconds
    132                 ts->tv_nsec += nsec_offset;
    133                 // Offset the seconds taking into account a nano-second overflow
    134                 ts->tv_sec = ts->tv_sec + ts->tv_nsec / 1000000000 + sec_offset;
    135                 // Trim the nanoseconds back there was an overflow
    136                 ts->tv_nsec = ts->tv_nsec % 1000000000;
    137             }
    138         }
    139         static bool TimeOfDayLaterThan (struct timespec &ts)
    140         {
    141             struct timespec now;
    142             OffsetTimeOfDay(&now);
    143             if (now.tv_sec > ts.tv_sec)
    144                 return true;
    145             else if (now.tv_sec < ts.tv_sec)
    146                 return false;
    147             else
    148             {
    149                 if (now.tv_nsec > ts.tv_nsec)
    150                     return true;
    151                 else
    152                     return false;
    153             }
    154         }
    155 protected:
    156     //------------------------------------------------------------------
    157     // Classes that inherit from DNBTimer can see and modify these
    158     //------------------------------------------------------------------
    159         std::unique_ptr<PThreadMutex> m_mutexAP;
    160         struct timeval  m_timeval;
    161 };
    162 
    163 #endif // #ifndef __DNBTimer_h__
    164