| // File: timer.cpp - Simple high-precision timer class. Supports Win32, X360, and POSIX/Linux |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <assert.h> |
| #include <time.h> |
| |
| #include "timer.h" |
| |
| #if defined(WIN32) |
| #include <windows.h> |
| #elif defined(_XBOX) |
| #include <xtl.h> |
| #endif |
| |
| unsigned long long timer::g_init_ticks; |
| unsigned long long timer::g_freq; |
| double timer::g_inv_freq; |
| |
| #if defined(WIN32) || defined(_XBOX) |
| inline void query_counter(timer_ticks *pTicks) |
| { |
| QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(pTicks)); |
| } |
| inline void query_counter_frequency(timer_ticks *pTicks) |
| { |
| QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(pTicks)); |
| } |
| #elif defined(__GNUC__) |
| #include <sys/timex.h> |
| inline void query_counter(timer_ticks *pTicks) |
| { |
| struct timeval cur_time; |
| gettimeofday(&cur_time, NULL); |
| *pTicks = static_cast<unsigned long long>(cur_time.tv_sec)*1000000ULL + static_cast<unsigned long long>(cur_time.tv_usec); |
| } |
| inline void query_counter_frequency(timer_ticks *pTicks) |
| { |
| *pTicks = 1000000; |
| } |
| #endif |
| |
| timer::timer() : |
| m_start_time(0), |
| m_stop_time(0), |
| m_started(false), |
| m_stopped(false) |
| { |
| if (!g_inv_freq) |
| init(); |
| } |
| |
| timer::timer(timer_ticks start_ticks) |
| { |
| if (!g_inv_freq) |
| init(); |
| |
| m_start_time = start_ticks; |
| |
| m_started = true; |
| m_stopped = false; |
| } |
| |
| void timer::start(timer_ticks start_ticks) |
| { |
| m_start_time = start_ticks; |
| |
| m_started = true; |
| m_stopped = false; |
| } |
| |
| void timer::start() |
| { |
| query_counter(&m_start_time); |
| |
| m_started = true; |
| m_stopped = false; |
| } |
| |
| void timer::stop() |
| { |
| assert(m_started); |
| |
| query_counter(&m_stop_time); |
| |
| m_stopped = true; |
| } |
| |
| double timer::get_elapsed_secs() const |
| { |
| assert(m_started); |
| if (!m_started) |
| return 0; |
| |
| timer_ticks stop_time = m_stop_time; |
| if (!m_stopped) |
| query_counter(&stop_time); |
| |
| timer_ticks delta = stop_time - m_start_time; |
| return delta * g_inv_freq; |
| } |
| |
| timer_ticks timer::get_elapsed_us() const |
| { |
| assert(m_started); |
| if (!m_started) |
| return 0; |
| |
| timer_ticks stop_time = m_stop_time; |
| if (!m_stopped) |
| query_counter(&stop_time); |
| |
| timer_ticks delta = stop_time - m_start_time; |
| return (delta * 1000000ULL + (g_freq >> 1U)) / g_freq; |
| } |
| |
| void timer::init() |
| { |
| if (!g_inv_freq) |
| { |
| query_counter_frequency(&g_freq); |
| g_inv_freq = 1.0f / g_freq; |
| |
| query_counter(&g_init_ticks); |
| } |
| } |
| |
| timer_ticks timer::get_init_ticks() |
| { |
| if (!g_inv_freq) |
| init(); |
| |
| return g_init_ticks; |
| } |
| |
| timer_ticks timer::get_ticks() |
| { |
| if (!g_inv_freq) |
| init(); |
| |
| timer_ticks ticks; |
| query_counter(&ticks); |
| return ticks - g_init_ticks; |
| } |
| |
| double timer::ticks_to_secs(timer_ticks ticks) |
| { |
| if (!g_inv_freq) |
| init(); |
| |
| return ticks * g_inv_freq; |
| } |
| |