compilation fixes
[wxWidgets.git] / src / common / stopwatch.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: 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 wxWindows Team
13 // License: wxWindows license
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 #ifndef WX_PRECOMP
32 #include "wx/intl.h"
33 #include "wx/log.h"
34 #endif //WX_PRECOMP
35
36 #include "wx/timer.h"
37 #include "wx/longlong.h"
38
39 // ----------------------------------------------------------------------------
40 // System headers
41 // ----------------------------------------------------------------------------
42
43 #if defined(__WIN32__)
44 #include <windows.h>
45 #endif
46
47 #if defined(__WIN32__) && !defined(HAVE_FTIME) && !defined(__MWERKS__)
48 #define HAVE_FTIME
49 #endif
50
51 #if defined(__VISAGECPP__) && !defined(HAVE_FTIME)
52 #define HAVE_FTIME
53 # if __IBMCPP__ >= 400
54 # define ftime(x) _ftime(x)
55 # endif
56 #endif
57
58 #if defined(__MWERKS__) && defined(__WXMSW__)
59 # undef HAVE_FTIME
60 # undef HAVE_GETTIMEOFDAY
61 #endif
62
63 #include <time.h>
64 #ifndef __WXMAC__
65 #include <sys/types.h> // for time_t
66 #endif
67
68 #if defined(HAVE_GETTIMEOFDAY)
69 #include <sys/time.h>
70 #include <unistd.h>
71 #elif defined(HAVE_FTIME)
72 #include <sys/timeb.h>
73 #endif
74
75 #ifdef __WXMAC__
76 #include <Timer.h>
77 #include <DriverServices.h>
78 #endif
79
80 // ----------------------------------------------------------------------------
81 // macros
82 // ----------------------------------------------------------------------------
83
84 // on some really old systems gettimeofday() doesn't have the second argument,
85 // define wxGetTimeOfDay() to hide this difference
86 #ifdef HAVE_GETTIMEOFDAY
87 #ifdef WX_GETTIMEOFDAY_NO_TZ
88 struct timezone;
89 #define wxGetTimeOfDay(tv, tz) gettimeofday(tv)
90 #else
91 #define wxGetTimeOfDay(tv, tz) gettimeofday((tv), (tz))
92 #endif
93 #endif // HAVE_GETTIMEOFDAY
94
95 // ============================================================================
96 // implementation
97 // ============================================================================
98
99 // ----------------------------------------------------------------------------
100 // wxStopWatch
101 // ----------------------------------------------------------------------------
102
103 #if wxUSE_STOPWATCH
104
105 void wxStopWatch::Start(long t)
106 {
107 m_t0 = wxGetLocalTimeMillis() - t;
108 m_pause = 0;
109 m_pauseCount = 0;
110 }
111
112 long wxStopWatch::GetElapsedTime() const
113 {
114 return (wxGetLocalTimeMillis() - m_t0).GetLo();
115 }
116
117 long wxStopWatch::Time() const
118 {
119 return m_pauseCount ? m_pause : GetElapsedTime();
120 }
121
122 #endif // wxUSE_STOPWATCH
123
124 // ----------------------------------------------------------------------------
125 // old timer functions superceded by wxStopWatch
126 // ----------------------------------------------------------------------------
127
128 #if wxUSE_LONGLONG
129
130 static wxLongLong wxStartTime = 0l;
131
132 // starts the global timer
133 void wxStartTimer()
134 {
135 wxStartTime = wxGetLocalTimeMillis();
136 }
137
138 // Returns elapsed time in milliseconds
139 long wxGetElapsedTime(bool resetTimer)
140 {
141 wxLongLong oldTime = wxStartTime;
142 wxLongLong newTime = wxGetLocalTimeMillis();
143
144 if ( resetTimer )
145 wxStartTime = newTime;
146
147 return (newTime - oldTime).GetLo();
148 }
149
150 #endif // wxUSE_LONGLONG
151
152 // ----------------------------------------------------------------------------
153 // the functions to get the current time and timezone info
154 // ----------------------------------------------------------------------------
155
156 // Get local time as seconds since 00:00:00, Jan 1st 1970
157 long wxGetLocalTime()
158 {
159 struct tm tm;
160 time_t t0, t1;
161
162 // This cannot be made static because mktime can overwrite it.
163 //
164 memset(&tm, 0, sizeof(tm));
165 tm.tm_year = 70;
166 tm.tm_mon = 0;
167 tm.tm_mday = 5; // not Jan 1st 1970 due to mktime 'feature'
168 tm.tm_hour = 0;
169 tm.tm_min = 0;
170 tm.tm_sec = 0;
171 tm.tm_isdst = -1; // let mktime guess
172
173 // Note that mktime assumes that the struct tm contains local time.
174 //
175 t1 = time(&t1); // now
176 t0 = mktime(&tm); // origin
177
178 // Return the difference in seconds.
179 //
180 if (( t0 != (time_t)-1 ) && ( t1 != (time_t)-1 ))
181 return (long)difftime(t1, t0) + (60 * 60 * 24 * 4);
182
183 wxLogSysError(_("Failed to get the local system time"));
184 return -1;
185 }
186
187 // Get UTC time as seconds since 00:00:00, Jan 1st 1970
188 long wxGetUTCTime()
189 {
190 struct tm tm;
191 struct tm *ptm;
192 time_t t0, t1;
193
194 // This cannot be made static because mktime can overwrite it
195 //
196 memset(&tm, 0, sizeof(tm));
197 tm.tm_year = 70;
198 tm.tm_mon = 0;
199 tm.tm_mday = 5; // not Jan 1st 1970 due to mktime 'feature'
200 tm.tm_hour = 0;
201 tm.tm_min = 0;
202 tm.tm_sec = 0;
203 tm.tm_isdst = -1; // let mktime guess
204
205 // Note that mktime assumes that the struct tm contains local time.
206 //
207 t1 = time(&t1); // now
208 t0 = mktime(&tm); // origin in localtime
209
210 if (( t0 != (time_t)-1 ) && ( t1 != (time_t)-1 ))
211 {
212 // To get t0 as GMT we convert to a struct tm with gmtime,
213 // and then back again.
214 //
215 ptm = gmtime(&t0);
216
217 if (ptm)
218 {
219 memcpy(&tm, ptm, sizeof(tm));
220 t0 = mktime(&tm);
221
222 if (t0 != (time_t)-1 )
223 return (long)difftime(t1, t0) + (60 * 60 * 24 * 4);
224 wxLogSysError(_("mktime() failed"));
225 }
226 else
227 {
228 wxLogSysError(_("gmtime() failed"));
229 }
230 }
231
232 wxLogError(_("Failed to get the UTC system time."));
233
234 return -1;
235 }
236
237 #if wxUSE_LONGLONG
238
239 // Get local time as milliseconds since 00:00:00, Jan 1st 1970
240 wxLongLong wxGetLocalTimeMillis()
241 {
242 wxLongLong val = 1000l;
243
244 // If possible, use a function which avoids conversions from
245 // broken-up time structures to milliseconds
246
247 #if defined(__WXMSW__) && defined(__MWERKS__)
248 // This should probably be the way all WXMSW compilers should do it
249 // Go direct to the OS for time
250
251 SYSTEMTIME thenst = { 1970, 1, 4, 1, 0, 0, 0, 0 }; // 00:00:00 Jan 1st 1970
252 FILETIME thenft;
253 SystemTimeToFileTime( &thenst, &thenft );
254 wxLongLong then( thenft.dwHighDateTime, thenft.dwLowDateTime ); // time in 100 nanoseconds
255
256 SYSTEMTIME nowst;
257 GetLocalTime( &nowst );
258 FILETIME nowft;
259 SystemTimeToFileTime( &nowst, &nowft );
260 wxLongLong now( nowft.dwHighDateTime, nowft.dwLowDateTime ); // time in 100 nanoseconds
261
262 return ( now - then ) / 10000.0; // time from 00:00:00 Jan 1st 1970 to now in milliseconds
263
264 #elif defined(HAVE_GETTIMEOFDAY)
265 struct timeval tp;
266 if ( wxGetTimeOfDay(&tp, (struct timezone *)NULL) != -1 )
267 {
268 val *= tp.tv_sec;
269 return (val + (tp.tv_usec / 1000));
270 }
271 else
272 {
273 wxLogError(_("wxGetTimeOfDay failed."));
274 return 0;
275 }
276 #elif defined(HAVE_FTIME)
277 struct timeb tp;
278
279 // ftime() is void and not int in some mingw32 headers, so don't
280 // test the return code (well, it shouldn't fail anyhow...)
281 (void)ftime(&tp);
282 val *= tp.time;
283 return (val + tp.millitm);
284 #elif defined(__WXMAC__)
285
286 static UInt64 gMilliAtStart = 0;
287
288 Nanoseconds upTime = AbsoluteToNanoseconds( UpTime() );
289
290 if ( gMilliAtStart == 0 )
291 {
292 time_t start = time(NULL);
293 gMilliAtStart = ((UInt64) start) * 1000000L;
294 gMilliAtStart -= upTime.lo / 1000 ;
295 gMilliAtStart -= ( ( (UInt64) upTime.hi ) << 32 ) / (1000 * 1000);
296 }
297
298 UInt64 millival = gMilliAtStart;
299 millival += upTime.lo / (1000 * 1000);
300 millival += ( ( (UInt64) upTime.hi ) << 32 ) / (1000 * 1000);
301 val = millival;
302
303 return val;
304 #else // no gettimeofday() nor ftime()
305 // We use wxGetLocalTime() to get the seconds since
306 // 00:00:00 Jan 1st 1970 and then whatever is available
307 // to get millisecond resolution.
308 //
309 // NOTE that this might lead to a problem if the clocks
310 // use different sources, so this approach should be
311 // avoided where possible.
312
313 val *= wxGetLocalTime();
314
315 // GRG: This will go soon as all WIN32 seem to have ftime
316 #if defined (__WIN32__)
317 // If your platform/compiler needs to use two different functions
318 // to get ms resolution, please do NOT just shut off these warnings,
319 // drop me a line instead at <guille@iies.es>
320 #warning "Possible clock skew bug in wxGetLocalTimeMillis()!"
321
322 SYSTEMTIME st;
323 ::GetLocalTime(&st);
324 val += st.wMilliseconds;
325 #else // !Win32
326 // If your platform/compiler does not support ms resolution please
327 // do NOT just shut off these warnings, drop me a line instead at
328 // <guille@iies.es>
329
330 #if defined(__VISUALC__) || defined (__WATCOMC__)
331 #pragma message("wxStopWatch will be up to second resolution!")
332 #elif defined(__BORLANDC__)
333 #pragma message "wxStopWatch will be up to second resolution!"
334 #else
335 #warning "wxStopWatch will be up to second resolution!"
336 #endif // compiler
337 #endif
338
339 return val;
340
341 #endif // time functions
342 }
343
344 #endif // wxUSE_LONGLONG
345
346