/*
This file is a part of KMC software distributed under GNU GPL 3 licence.
The homepage of the KMC project is http://sun.aei.polsl.pl/kmc
Authors: Marek Kokot
Version: 3.0.0
Date : 2017-01-28
*/
#ifdef _WIN32
#include <windows.h>
#endif
#include <cstdio> // NULL
#include "thread_watch.h"
#ifdef _WIN32
typedef struct
{
ULARGE_INTEGER start;
ULARGE_INTEGER stop;
} thread_watch_t;
class CThreadWatchImpl
{
thread_watch_t timer_kernel, timer_user;
LARGE_INTEGER frequency;
double LIToSecs(LARGE_INTEGER & L);
public:
CThreadWatchImpl();
void StartTimer();
void StopTimer();
double GetElapsedTime();
};
double CThreadWatchImpl::LIToSecs(LARGE_INTEGER & L)
{
return ((double)L.QuadPart / (double)frequency.QuadPart);
}
// **********************************************************
CThreadWatchImpl::CThreadWatchImpl()
{
timer_kernel.start.QuadPart = 0;
timer_kernel.stop.QuadPart = 0;
timer_user.start.QuadPart = 0;
timer_user.stop.QuadPart = 0;
// QueryPerformanceFrequency( &frequency );
// frequency = 1; // 100ns
}
// **********************************************************
void CThreadWatchImpl::StartTimer()
{
FILETIME CreationTime, ExitTime, KernelTime, UserTime;
GetThreadTimes(GetCurrentThread(), &CreationTime, &ExitTime, &KernelTime, &UserTime);
timer_kernel.start.LowPart = KernelTime.dwLowDateTime;
timer_kernel.start.HighPart = KernelTime.dwHighDateTime;
timer_user.start.LowPart = UserTime.dwLowDateTime;
timer_user.start.HighPart = UserTime.dwHighDateTime;
}
// **********************************************************
void CThreadWatchImpl::StopTimer()
{
FILETIME CreationTime, ExitTime, KernelTime, UserTime;
GetThreadTimes(GetCurrentThread(), &CreationTime, &ExitTime, &KernelTime, &UserTime);
// QueryPerformanceCounter(&timer.stop);
timer_kernel.stop.LowPart = KernelTime.dwLowDateTime;
timer_kernel.stop.HighPart = KernelTime.dwHighDateTime;
timer_user.stop.LowPart = UserTime.dwLowDateTime;
timer_user.stop.HighPart = UserTime.dwHighDateTime;
}
// **********************************************************
double CThreadWatchImpl::GetElapsedTime()
{
/* LARGE_INTEGER time;
time.QuadPart = timer.stop.QuadPart - timer.start.QuadPart;
return LIToSecs( time) ;*/
LARGE_INTEGER time;
time.QuadPart = (timer_kernel.stop.QuadPart - timer_kernel.start.QuadPart);
time.QuadPart += (timer_user.stop.QuadPart - timer_user.start.QuadPart);
return (double)time.QuadPart / 1e7; // 100ns clock
}
CThreadWatch::CThreadWatch()
{
pimpl = new CThreadWatchImpl;
}
void CThreadWatch::StartTimer()
{
pimpl->StartTimer();
}
void CThreadWatch::StopTimer()
{
pimpl->StopTimer();
}
double CThreadWatch::GetElapsedTime()
{
return pimpl->GetElapsedTime();
}
CThreadWatch::~CThreadWatch()
{
delete pimpl;
}
#else
// **********************************************************
// **********************************************************
// CThreadWatch
// **********************************************************
/*double CThreadWatch::LIToSecs( LARGE_INTEGER & L)
{
return 1.0;
}*/
// **********************************************************
CThreadWatch::CThreadWatch()
{
}
// **********************************************************
void CThreadWatch::StartTimer()
{
rusage usage;
getrusage(RUSAGE_THREAD, &usage);
start_user = usage.ru_utime;
start_kernel = usage.ru_stime;
}
// **********************************************************
void CThreadWatch::StopTimer()
{
rusage usage;
getrusage(RUSAGE_THREAD, &usage);
stop_user = usage.ru_utime;
stop_kernel = usage.ru_stime;
}
// **********************************************************
double CThreadWatch::GetElapsedTime()
{
double ret = 0.0;
ret += stop_user.tv_sec + stop_user.tv_usec / 1000000.0;
ret += stop_kernel.tv_sec + stop_kernel.tv_usec / 1000000.0;
ret -= start_user.tv_sec + start_user.tv_usec / 1000000.0;
ret -= start_kernel.tv_sec + start_kernel.tv_usec / 1000000.0;
return ret;
}
#endif