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