• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // File: timer.cpp - Simple high-precision timer class. Supports Win32, X360, and POSIX/Linux
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <assert.h>
5 #include <time.h>
6 
7 #include "timer.h"
8 
9 #if defined(WIN32)
10 #include <windows.h>
11 #elif defined(_XBOX)
12 #include <xtl.h>
13 #endif
14 
15 unsigned long long timer::g_init_ticks;
16 unsigned long long timer::g_freq;
17 double timer::g_inv_freq;
18 
19 #if defined(WIN32) || defined(_XBOX)
query_counter(timer_ticks * pTicks)20 inline void query_counter(timer_ticks *pTicks)
21 {
22    QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(pTicks));
23 }
query_counter_frequency(timer_ticks * pTicks)24 inline void query_counter_frequency(timer_ticks *pTicks)
25 {
26    QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(pTicks));
27 }
28 #elif defined(__GNUC__)
29 #include <sys/timex.h>
query_counter(timer_ticks * pTicks)30 inline void query_counter(timer_ticks *pTicks)
31 {
32    struct timeval cur_time;
33    gettimeofday(&cur_time, NULL);
34    *pTicks = static_cast<unsigned long long>(cur_time.tv_sec)*1000000ULL + static_cast<unsigned long long>(cur_time.tv_usec);
35 }
query_counter_frequency(timer_ticks * pTicks)36 inline void query_counter_frequency(timer_ticks *pTicks)
37 {
38    *pTicks = 1000000;
39 }
40 #endif
41 
timer()42 timer::timer() :
43    m_start_time(0),
44    m_stop_time(0),
45    m_started(false),
46    m_stopped(false)
47 {
48    if (!g_inv_freq)
49       init();
50 }
51 
timer(timer_ticks start_ticks)52 timer::timer(timer_ticks start_ticks)
53 {
54    if (!g_inv_freq)
55       init();
56 
57    m_start_time = start_ticks;
58 
59    m_started = true;
60    m_stopped = false;
61 }
62 
start(timer_ticks start_ticks)63 void timer::start(timer_ticks start_ticks)
64 {
65    m_start_time = start_ticks;
66 
67    m_started = true;
68    m_stopped = false;
69 }
70 
start()71 void timer::start()
72 {
73    query_counter(&m_start_time);
74 
75    m_started = true;
76    m_stopped = false;
77 }
78 
stop()79 void timer::stop()
80 {
81    assert(m_started);
82 
83    query_counter(&m_stop_time);
84 
85    m_stopped = true;
86 }
87 
get_elapsed_secs() const88 double timer::get_elapsed_secs() const
89 {
90    assert(m_started);
91    if (!m_started)
92       return 0;
93 
94    timer_ticks stop_time = m_stop_time;
95    if (!m_stopped)
96       query_counter(&stop_time);
97 
98    timer_ticks delta = stop_time - m_start_time;
99    return delta * g_inv_freq;
100 }
101 
get_elapsed_us() const102 timer_ticks timer::get_elapsed_us() const
103 {
104    assert(m_started);
105    if (!m_started)
106       return 0;
107 
108    timer_ticks stop_time = m_stop_time;
109    if (!m_stopped)
110       query_counter(&stop_time);
111 
112    timer_ticks delta = stop_time - m_start_time;
113    return (delta * 1000000ULL + (g_freq >> 1U)) / g_freq;
114 }
115 
init()116 void timer::init()
117 {
118    if (!g_inv_freq)
119    {
120       query_counter_frequency(&g_freq);
121       g_inv_freq = 1.0f / g_freq;
122 
123       query_counter(&g_init_ticks);
124    }
125 }
126 
get_init_ticks()127 timer_ticks timer::get_init_ticks()
128 {
129    if (!g_inv_freq)
130       init();
131 
132    return g_init_ticks;
133 }
134 
get_ticks()135 timer_ticks timer::get_ticks()
136 {
137    if (!g_inv_freq)
138       init();
139 
140    timer_ticks ticks;
141    query_counter(&ticks);
142    return ticks - g_init_ticks;
143 }
144 
ticks_to_secs(timer_ticks ticks)145 double timer::ticks_to_secs(timer_ticks ticks)
146 {
147    if (!g_inv_freq)
148       init();
149 
150    return ticks * g_inv_freq;
151 }
152 
153