Use wxGetUTCTimeUSec() in wxStopWatch under Unix for higher precision.
[wxWidgets.git] / src / common / stopwatch.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/stopwatch.cpp
3 // Purpose: wxStopWatch and other non-GUI stuff from wx/timer.h
4 // Author:
5 // Original version by Julian Smart
6 // Vadim Zeitlin got rid of all ifdefs (11.12.99)
7 // Sylvain Bougnoux added wxStopWatch class
8 // Guillermo Rodriguez <guille@iies.es> rewrote from scratch (Dic/99)
9 // Modified by:
10 // Created: 20.06.2003 (extracted from common/timercmn.cpp)
11 // RCS-ID: $Id$
12 // Copyright: (c) 1998-2003 wxWidgets Team
13 // Licence: wxWindows licence
14 ///////////////////////////////////////////////////////////////////////////////
15
16 // ============================================================================
17 // declarations
18 // ============================================================================
19
20 // ----------------------------------------------------------------------------
21 // headers
22 // ----------------------------------------------------------------------------
23
24 // for compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #include "wx/stopwatch.h"
32
33 #if wxUSE_STOPWATCH
34
35 #ifndef WX_PRECOMP
36 #ifdef __WXMSW__
37 #include "wx/msw/wrapwin.h"
38 #endif
39 #include "wx/log.h"
40 #endif //WX_PRECOMP
41
42 // ============================================================================
43 // implementation
44 // ============================================================================
45
46 // ----------------------------------------------------------------------------
47 // wxStopWatch
48 // ----------------------------------------------------------------------------
49
50 namespace
51 {
52
53 #ifdef __WXMSW__
54
55 struct PerfCounter
56 {
57 PerfCounter()
58 {
59 init = false;
60 }
61
62 bool CanBeUsed() const
63 {
64 return freq.QuadPart != 0;
65 }
66
67 wxCriticalSection cs;
68 LARGE_INTEGER freq;
69 bool init;
70 } gs_perfCounter;
71
72 #endif // __WXMSW__
73
74 const int MILLISECONDS_PER_SECOND = 1000;
75 const int MICROSECONDS_PER_MILLISECOND = 1000;
76 const int MICROSECONDS_PER_SECOND = 1000*1000;
77
78 } // anonymous namespace
79
80 void wxStopWatch::DoStart()
81 {
82 #ifdef __WXMSW__
83 if ( !gs_perfCounter.init )
84 {
85 wxCriticalSectionLocker lock(gs_perfCounter.cs);
86 ::QueryPerformanceFrequency(&gs_perfCounter.freq);
87
88 // Just a sanity check: it's not supposed to happen but verify that
89 // ::QueryPerformanceCounter() succeeds so that we can really use it.
90 LARGE_INTEGER counter;
91 if ( !::QueryPerformanceCounter(&counter) )
92 {
93 wxLogDebug("QueryPerformanceCounter() unexpected failed (%s), "
94 "will not use it.", wxSysErrorMsg());
95
96 gs_perfCounter.freq.QuadPart = 0;
97 }
98
99 gs_perfCounter.init = true;
100 }
101 #endif // __WXMSW__
102
103 m_t0 = GetCurrentClockValue();
104 }
105
106 wxLongLong wxStopWatch::GetClockFreq() const
107 {
108 #ifdef __WXMSW__
109 // Under MSW we use the high resolution performance counter timer which has
110 // its own frequency (usually related to the CPU clock speed).
111 if ( gs_perfCounter.CanBeUsed() )
112 return gs_perfCounter.freq.QuadPart;
113 #endif // __WXMSW__
114
115 #ifdef HAVE_GETTIMEOFDAY
116 // With gettimeofday() we can have nominally microsecond precision and
117 // while this is not the case in practice, it's still better than
118 // millisecond.
119 return MICROSECONDS_PER_SECOND;
120 #else // !HAVE_GETTIMEOFDAY
121 // Currently milliseconds are used everywhere else.
122 return MILLISECONDS_PER_SECOND;
123 #endif // HAVE_GETTIMEOFDAY/!HAVE_GETTIMEOFDAY
124 }
125
126 void wxStopWatch::Start(long t0)
127 {
128 DoStart();
129
130 m_t0 -= (wxLongLong(t0)*GetClockFreq())/MILLISECONDS_PER_SECOND;
131 }
132
133 wxLongLong wxStopWatch::GetCurrentClockValue() const
134 {
135 #ifdef __WXMSW__
136 if ( gs_perfCounter.CanBeUsed() )
137 {
138 LARGE_INTEGER counter;
139 ::QueryPerformanceCounter(&counter);
140 return counter.QuadPart;
141 }
142 #endif // __WXMSW__
143
144 #ifdef HAVE_GETTIMEOFDAY
145 return wxGetUTCTimeUSec();
146 #else // !HAVE_GETTIMEOFDAY
147 return wxGetUTCTimeMillis();
148 #endif // HAVE_GETTIMEOFDAY/!HAVE_GETTIMEOFDAY
149 }
150
151 wxLongLong wxStopWatch::TimeInMicro() const
152 {
153 const wxLongLong elapsed(m_pauseCount ? m_elapsedBeforePause
154 : GetCurrentClockValue() - m_t0);
155
156 return (elapsed*MICROSECONDS_PER_SECOND)/GetClockFreq();
157 }
158
159 #endif // wxUSE_STOPWATCH
160
161 // ----------------------------------------------------------------------------
162 // old timer functions superceded by wxStopWatch
163 // ----------------------------------------------------------------------------
164
165 #if wxUSE_LONGLONG
166
167 static wxLongLong wxStartTime = 0l;
168
169 // starts the global timer
170 void wxStartTimer()
171 {
172 wxStartTime = wxGetUTCTimeMillis();
173 }
174
175 // Returns elapsed time in milliseconds
176 long wxGetElapsedTime(bool resetTimer)
177 {
178 wxLongLong oldTime = wxStartTime;
179 wxLongLong newTime = wxGetUTCTimeMillis();
180
181 if ( resetTimer )
182 wxStartTime = newTime;
183
184 return (newTime - oldTime).GetLo();
185 }
186
187 #endif // wxUSE_LONGLONG