#ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_DNBTIMER_H
#define LLDB_TOOLS_DEBUGSERVER_SOURCE_DNBTIMER_H
#include "DNBDefs.h"
#include "PThreadMutex.h"
#include <cstdint>
#include <memory>
#include <sys/time.h>
class DNBTimer {
public:
DNBTimer(bool threadSafe) : m_mutexAP() {
if (threadSafe)
m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
Reset();
}
DNBTimer(const DNBTimer &rhs) : m_mutexAP() {
if (rhs.IsThreadSafe())
m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE));
m_timeval = rhs.m_timeval;
}
DNBTimer &operator=(const DNBTimer &rhs) {
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; }
void Reset() {
PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get());
gettimeofday(&m_timeval, NULL);
}
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;
}
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;
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;
struct timeval now;
gettimeofday(&now, NULL);
TIMEVAL_TO_TIMESPEC(&now, ts);
if (sec_offset != 0 || nsec_offset != 0) {
ts->tv_nsec += nsec_offset;
ts->tv_sec = ts->tv_sec + ts->tv_nsec / 1000000000 + sec_offset;
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:
std::unique_ptr<PThreadMutex> m_mutexAP;
struct timeval m_timeval;
};
#endif