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 //------------------------------------------------------------------ DNBTimer(bool threadSafe)29 DNBTimer (bool threadSafe) : 30 m_mutexAP() 31 { 32 if (threadSafe) 33 m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); 34 Reset(); 35 } 36 DNBTimer(const DNBTimer & rhs)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 ~DNBTimer()57 ~DNBTimer () 58 { 59 } 60 61 bool IsThreadSafe()62 IsThreadSafe() const 63 { 64 return m_mutexAP.get() != NULL; 65 } 66 //------------------------------------------------------------------ 67 // Reset the time value to now 68 //------------------------------------------------------------------ 69 void Reset()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 TotalMicroSeconds()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 GetTime(uint32_t & sec,uint32_t & usec)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 ElapsedMicroSeconds(bool update)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 GetTimeOfDay()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 } TimeOfDayLaterThan(struct timespec & ts)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