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