Added wxGetUTCTimeMillis() and wxGetUTCTimeUSec().
[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 #ifndef WX_PRECOMP
34 #ifdef __WXMSW__
35 #include "wx/msw/wrapwin.h"
36 #endif
37 #include "wx/intl.h"
38 #include "wx/log.h"
39 #endif //WX_PRECOMP
40
41 // ----------------------------------------------------------------------------
42 // System headers
43 // ----------------------------------------------------------------------------
44
45 #if defined(__VISAGECPP__) && !defined(HAVE_FTIME)
46 #define HAVE_FTIME
47 # if __IBMCPP__ >= 400
48 # define ftime(x) _ftime(x)
49 # endif
50 #endif
51
52 #if defined(__MWERKS__) && defined(__WXMSW__)
53 # undef HAVE_FTIME
54 # undef HAVE_GETTIMEOFDAY
55 #endif
56
57 #ifndef __WXPALMOS5__
58 #ifndef __WXWINCE__
59 #include <time.h>
60 #else
61 #include "wx/msw/private.h"
62 #include "wx/msw/wince/time.h"
63 #endif
64 #endif // __WXPALMOS5__
65
66
67 #if !defined(__WXMAC__) && !defined(__WXWINCE__)
68 #include <sys/types.h> // for time_t
69 #endif
70
71 #if defined(HAVE_GETTIMEOFDAY)
72 #include <sys/time.h>
73 #include <unistd.h>
74 #elif defined(HAVE_FTIME)
75 #include <sys/timeb.h>
76 #endif
77
78 #ifdef __WXPALMOS__
79 #include <DateTime.h>
80 #include <TimeMgr.h>
81 #include <SystemMgr.h>
82 #endif
83
84 // ============================================================================
85 // implementation
86 // ============================================================================
87
88 // ----------------------------------------------------------------------------
89 // wxStopWatch
90 // ----------------------------------------------------------------------------
91
92 #if wxUSE_STOPWATCH
93
94 namespace
95 {
96
97 #ifdef __WXMSW__
98
99 struct PerfCounter
100 {
101 PerfCounter()
102 {
103 init = false;
104 }
105
106 bool CanBeUsed() const
107 {
108 return freq.QuadPart != 0;
109 }
110
111 wxCriticalSection cs;
112 LARGE_INTEGER freq;
113 bool init;
114 } gs_perfCounter;
115
116 #endif // __WXMSW__
117
118 const int MILLISECONDS_PER_SECOND = 1000;
119 const int MICROSECONDS_PER_MILLISECOND = 1000;
120 const int MICROSECONDS_PER_SECOND = 1000*1000;
121
122 } // anonymous namespace
123
124 void wxStopWatch::DoStart()
125 {
126 #ifdef __WXMSW__
127 if ( !gs_perfCounter.init )
128 {
129 wxCriticalSectionLocker lock(gs_perfCounter.cs);
130 ::QueryPerformanceFrequency(&gs_perfCounter.freq);
131
132 // Just a sanity check: it's not supposed to happen but verify that
133 // ::QueryPerformanceCounter() succeeds so that we can really use it.
134 LARGE_INTEGER counter;
135 if ( !::QueryPerformanceCounter(&counter) )
136 {
137 wxLogDebug("QueryPerformanceCounter() unexpected failed (%s), "
138 "will not use it.", wxSysErrorMsg());
139
140 gs_perfCounter.freq.QuadPart = 0;
141 }
142
143 gs_perfCounter.init = true;
144 }
145 #endif // __WXMSW__
146
147 m_t0 = GetCurrentClockValue();
148 }
149
150 wxLongLong wxStopWatch::GetClockFreq() const
151 {
152 #ifdef __WXMSW__
153 // Under MSW we use the high resolution performance counter timer which has
154 // its own frequency (usually related to the CPU clock speed).
155 if ( gs_perfCounter.CanBeUsed() )
156 return gs_perfCounter.freq.QuadPart;
157 #endif // __WXMSW__
158
159 // Currently milliseconds are used everywhere else.
160 return MILLISECONDS_PER_SECOND;
161 }
162
163 void wxStopWatch::Start(long t0)
164 {
165 DoStart();
166
167 m_t0 -= (wxLongLong(t0)*GetClockFreq())/MILLISECONDS_PER_SECOND;
168 }
169
170 wxLongLong wxStopWatch::GetCurrentClockValue() const
171 {
172 #ifdef __WXMSW__
173 if ( gs_perfCounter.CanBeUsed() )
174 {
175 LARGE_INTEGER counter;
176 ::QueryPerformanceCounter(&counter);
177 return counter.QuadPart;
178 }
179 #endif // __WXMSW__
180
181 return wxGetLocalTimeMillis();
182 }
183
184 wxLongLong wxStopWatch::TimeInMicro() const
185 {
186 const wxLongLong elapsed(m_pauseCount ? m_elapsedBeforePause
187 : GetCurrentClockValue() - m_t0);
188
189 return (elapsed*MICROSECONDS_PER_SECOND)/GetClockFreq();
190 }
191
192 #endif // wxUSE_STOPWATCH
193
194 // ----------------------------------------------------------------------------
195 // old timer functions superceded by wxStopWatch
196 // ----------------------------------------------------------------------------
197
198 #if wxUSE_LONGLONG
199
200 static wxLongLong wxStartTime = 0l;
201
202 // starts the global timer
203 void wxStartTimer()
204 {
205 wxStartTime = wxGetLocalTimeMillis();
206 }
207
208 // Returns elapsed time in milliseconds
209 long wxGetElapsedTime(bool resetTimer)
210 {
211 wxLongLong oldTime = wxStartTime;
212 wxLongLong newTime = wxGetLocalTimeMillis();
213
214 if ( resetTimer )
215 wxStartTime = newTime;
216
217 return (newTime - oldTime).GetLo();
218 }
219
220 #endif // wxUSE_LONGLONG
221
222 // ----------------------------------------------------------------------------
223 // the functions to get the current time and timezone info
224 // ----------------------------------------------------------------------------
225
226 // Get local time as seconds since 00:00:00, Jan 1st 1970
227 long wxGetLocalTime()
228 {
229 struct tm tm;
230 time_t t0, t1;
231
232 // This cannot be made static because mktime can overwrite it.
233 //
234 memset(&tm, 0, sizeof(tm));
235 tm.tm_year = 70;
236 tm.tm_mon = 0;
237 tm.tm_mday = 5; // not Jan 1st 1970 due to mktime 'feature'
238 tm.tm_hour = 0;
239 tm.tm_min = 0;
240 tm.tm_sec = 0;
241 tm.tm_isdst = -1; // let mktime guess
242
243 // Note that mktime assumes that the struct tm contains local time.
244 //
245 t1 = time(&t1); // now
246 t0 = mktime(&tm); // origin
247
248 // Return the difference in seconds.
249 //
250 if (( t0 != (time_t)-1 ) && ( t1 != (time_t)-1 ))
251 return (long)difftime(t1, t0) + (60 * 60 * 24 * 4);
252
253 wxLogSysError(_("Failed to get the local system time"));
254 return -1;
255 }
256
257 // Get UTC time as seconds since 00:00:00, Jan 1st 1970
258 long wxGetUTCTime()
259 {
260 return (long)time(NULL);
261 }
262
263 #if wxUSE_LONGLONG
264
265 wxLongLong wxGetUTCTimeUSec()
266 {
267 #if defined(__WXMSW__)
268 FILETIME ft;
269 ::GetSystemTimeAsFileTime(&ft);
270
271 // FILETIME is in 100ns or 0.1us since 1601-01-01, transform to us since
272 // 1970-01-01.
273 wxLongLong t(ft.dwHighDateTime, ft.dwLowDateTime);
274 t /= 10;
275 t -= wxLL(11644473600000000); // Unix - Windows epochs difference in us.
276 return t;
277 #else // non-MSW
278
279 #ifdef HAVE_GETTIMEOFDAY
280 timeval tv;
281 if ( wxGetTimeOfDay(&tv) != -1 )
282 {
283 wxLongLong val(tv.tv_sec);
284 val *= MICROSECONDS_PER_SECOND;
285 val += tv.tv_usec;
286 return val;
287 }
288 #endif // HAVE_GETTIMEOFDAY
289
290 // Fall back to lesser precision function.
291 return wxGetUTCTimeMillis()*1000;
292 #endif // MSW/!MSW
293 }
294
295 // Get local time as milliseconds since 00:00:00, Jan 1st 1970
296 wxLongLong wxGetUTCTimeMillis()
297 {
298 wxLongLong val = 1000l;
299
300 // If possible, use a function which avoids conversions from
301 // broken-up time structures to milliseconds
302 #if defined(__WXPALMOS__)
303 DateTimeType thenst;
304 thenst.second = 0;
305 thenst.minute = 0;
306 thenst.hour = 0;
307 thenst.day = 1;
308 thenst.month = 1;
309 thenst.year = 1970;
310 thenst.weekDay = 5;
311 uint32_t now = TimGetSeconds();
312 uint32_t then = TimDateTimeToSeconds (&thenst);
313 return SysTimeToMilliSecs(SysTimeInSecs(now - then));
314 #elif defined(__WXMSW__)
315 FILETIME ft;
316 ::GetSystemTimeAsFileTime(&ft);
317
318 // FILETIME is expressed in 100ns (or 0.1us) units since 1601-01-01,
319 // transform them to ms since 1970-01-01.
320 wxLongLong t(ft.dwHighDateTime, ft.dwLowDateTime);
321 t /= 10000;
322 t -= wxLL(11644473600000); // Unix - Windows epochs difference in ms.
323 return t;
324 #elif defined(HAVE_GETTIMEOFDAY)
325 struct timeval tp;
326 if ( wxGetTimeOfDay(&tp) != -1 )
327 {
328 val *= tp.tv_sec;
329 return (val + (tp.tv_usec / 1000));
330 }
331 else
332 {
333 wxLogError(_("wxGetTimeOfDay failed."));
334 return 0;
335 }
336 #elif defined(HAVE_FTIME)
337 struct timeb tp;
338
339 // ftime() is void and not int in some mingw32 headers, so don't
340 // test the return code (well, it shouldn't fail anyhow...)
341 (void)::ftime(&tp);
342 val *= tp.time;
343 return (val + tp.millitm);
344 #else // no gettimeofday() nor ftime()
345 // If your platform/compiler does not support ms resolution please
346 // do NOT just shut off these warnings, drop me a line instead at
347 // <guille@iies.es>
348
349 #if defined(__VISUALC__) || defined (__WATCOMC__)
350 #pragma message("wxStopWatch will be up to second resolution!")
351 #elif defined(__BORLANDC__)
352 #pragma message "wxStopWatch will be up to second resolution!"
353 #else
354 #warning "wxStopWatch will be up to second resolution!"
355 #endif // compiler
356
357 val *= wxGetUTCTime();
358 return val;
359 #endif // time functions
360 }
361
362 wxLongLong wxGetLocalTimeMillis()
363 {
364 return wxGetUTCTimeMillis() - wxGetTimeZone()*MILLISECONDS_PER_SECOND;
365 }
366
367 #else // !wxUSE_LONGLONG
368
369 double wxGetLocalTimeMillis(void)
370 {
371 return (double(clock()) / double(CLOCKS_PER_SEC)) * 1000.0;
372 }
373
374 #endif // wxUSE_LONGLONG/!wxUSE_LONGLONG