//===-- DNBTimer.h ----------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Created by Greg Clayton on 12/13/07. // //===----------------------------------------------------------------------===// #ifndef __DNBTimer_h__ #define __DNBTimer_h__ #include "DNBDefs.h" #include "PThreadMutex.h" #include #include #include class DNBTimer { public: //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ DNBTimer(bool threadSafe) : m_mutexAP() { if (threadSafe) m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); Reset(); } DNBTimer(const DNBTimer &rhs) : m_mutexAP() { // Create a new mutex to make this timer thread safe as well if // the timer we are copying is thread safe if (rhs.IsThreadSafe()) m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); m_timeval = rhs.m_timeval; } DNBTimer &operator=(const DNBTimer &rhs) { // Create a new mutex to make this timer thread safe as well if // the timer we are copying is thread safe if (rhs.IsThreadSafe()) m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); m_timeval = rhs.m_timeval; return *this; } ~DNBTimer() {} bool IsThreadSafe() const { return m_mutexAP.get() != NULL; } //------------------------------------------------------------------ // Reset the time value to now //------------------------------------------------------------------ void Reset() { PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); gettimeofday(&m_timeval, NULL); } //------------------------------------------------------------------ // Get the total mircoseconds since Jan 1, 1970 //------------------------------------------------------------------ uint64_t TotalMicroSeconds() const { PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); return (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec; } void GetTime(uint64_t &sec, uint32_t &usec) const { PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); sec = m_timeval.tv_sec; usec = m_timeval.tv_usec; } //------------------------------------------------------------------ // Return the number of microseconds elapsed between now and the // m_timeval //------------------------------------------------------------------ uint64_t ElapsedMicroSeconds(bool update) { PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); struct timeval now; gettimeofday(&now, NULL); uint64_t now_usec = (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec; uint64_t this_usec = (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec; uint64_t elapsed = now_usec - this_usec; // Update the timer time value if requeseted if (update) m_timeval = now; return elapsed; } static uint64_t GetTimeOfDay() { struct timeval now; gettimeofday(&now, NULL); uint64_t now_usec = (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec; return now_usec; } static void OffsetTimeOfDay(struct timespec *ts, __darwin_time_t sec_offset = 0, long nsec_offset = 0) { if (ts == NULL) return; // Get the current time in a timeval structure struct timeval now; gettimeofday(&now, NULL); // Morph it into a timespec TIMEVAL_TO_TIMESPEC(&now, ts); // Offset the timespec if requested if (sec_offset != 0 || nsec_offset != 0) { // Offset the nano seconds ts->tv_nsec += nsec_offset; // Offset the seconds taking into account a nano-second overflow ts->tv_sec = ts->tv_sec + ts->tv_nsec / 1000000000 + sec_offset; // Trim the nanoseconds back there was an overflow ts->tv_nsec = ts->tv_nsec % 1000000000; } } static bool TimeOfDayLaterThan(struct timespec &ts) { struct timespec now; OffsetTimeOfDay(&now); if (now.tv_sec > ts.tv_sec) return true; else if (now.tv_sec < ts.tv_sec) return false; else { if (now.tv_nsec > ts.tv_nsec) return true; else return false; } } protected: //------------------------------------------------------------------ // Classes that inherit from DNBTimer can see and modify these //------------------------------------------------------------------ std::unique_ptr m_mutexAP; struct timeval m_timeval; }; #endif // #ifndef __DNBTimer_h__