home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / common / timercmn.cpp < prev    next >
C/C++ Source or Header  |  2002-10-15  |  12KB  |  404 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        common/timercmn.cpp
  3. // Purpose:     Common timer implementation
  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:     04/01/98
  11. // RCS-ID:      $Id: timercmn.cpp,v 1.62.2.2 2002/10/15 16:02:54 JS Exp $
  12. // Copyright:   (c) Julian Smart and Markus Holzem
  13. //              (c) 1999 Guillermo Rodriguez <guille@iies.es>
  14. // Licence:     wxWindows license
  15. /////////////////////////////////////////////////////////////////////////////
  16.  
  17. // ============================================================================
  18. // declarations
  19. // ============================================================================
  20.  
  21. // ----------------------------------------------------------------------------
  22. // wxWin headers
  23. // ----------------------------------------------------------------------------
  24.  
  25. #ifdef __GNUG__
  26.     #pragma implementation "timerbase.h"
  27. #endif
  28.  
  29. // For compilers that support precompilation, includes "wx.h".
  30. #include "wx/wxprec.h"
  31.  
  32. #ifdef __BORLANDC__
  33.     #pragma hdrstop
  34. #endif
  35.  
  36. #ifndef WX_PRECOMP
  37.     #include "wx/intl.h"
  38.     #include "wx/log.h"
  39.     #include "wx/thread.h"
  40. #endif
  41.  
  42. #include "wx/timer.h"
  43. #include "wx/longlong.h"
  44.  
  45. // ----------------------------------------------------------------------------
  46. // System headers
  47. // ----------------------------------------------------------------------------
  48.  
  49. #if defined(__WIN32__)
  50.     #include <windows.h>
  51. #endif
  52.  
  53. #if defined(__WIN32__) && !defined(HAVE_FTIME) && !defined(__MWERKS__)
  54.     #define HAVE_FTIME
  55. #endif
  56.  
  57. #if defined(__VISAGECPP__) && !defined(HAVE_FTIME)
  58.     #define HAVE_FTIME
  59. #  if __IBMCPP__ >= 400
  60.     #  define ftime(x) _ftime(x)
  61. #  endif
  62. #endif
  63.  
  64. #if defined(__MWERKS__) && defined(__WXMSW__)
  65. #   undef HAVE_FTIME
  66. #   undef HAVE_GETTIMEOFDAY
  67. #endif
  68.  
  69. #include <time.h>
  70. #ifndef __WXMAC__
  71.     #include <sys/types.h>      // for time_t
  72. #endif
  73.  
  74. #if defined(HAVE_GETTIMEOFDAY)
  75.     #include <sys/time.h>
  76.     #include <unistd.h>
  77. #elif defined(HAVE_FTIME)
  78.     #include <sys/timeb.h>
  79. #endif
  80.  
  81. #ifdef __WXMAC__
  82.     #include <Timer.h>
  83.     #include <DriverServices.h>
  84. #endif
  85. // ----------------------------------------------------------------------------
  86. // wxWin macros
  87. // ----------------------------------------------------------------------------
  88.  
  89. #if wxUSE_GUI && wxUSE_TIMER
  90.     IMPLEMENT_DYNAMIC_CLASS(wxTimerEvent, wxEvent)
  91. #endif // wxUSE_GUI
  92.  
  93. // ----------------------------------------------------------------------------
  94. // macros
  95. // ----------------------------------------------------------------------------
  96.  
  97. // on some really old systems gettimeofday() doesn't have the second argument,
  98. // define wxGetTimeOfDay() to hide this difference
  99. #ifdef HAVE_GETTIMEOFDAY
  100.     #ifdef WX_GETTIMEOFDAY_NO_TZ
  101.         struct timezone;
  102.         #define wxGetTimeOfDay(tv, tz)      gettimeofday(tv)
  103.     #else
  104.         #define wxGetTimeOfDay(tv, tz)      gettimeofday((tv), (tz))
  105.     #endif
  106. #endif // HAVE_GETTIMEOFDAY
  107.  
  108. // ============================================================================
  109. // implementation
  110. // ============================================================================
  111.  
  112. // ----------------------------------------------------------------------------
  113. // wxTimerBase
  114. // ----------------------------------------------------------------------------
  115.  
  116. #if wxUSE_GUI && wxUSE_TIMER
  117.  
  118. wxTimerBase::~wxTimerBase()
  119. {
  120.     // this destructor is required for Darwin
  121. }
  122.  
  123. void wxTimerBase::Notify()
  124. {
  125.     // the base class version generates an event if it has owner - which it
  126.     // should because otherwise nobody can process timer events
  127.     wxCHECK_RET( m_owner, _T("wxTimer::Notify() should be overridden.") );
  128.  
  129.     wxTimerEvent event(m_idTimer, m_milli);
  130.     (void)m_owner->ProcessEvent(event);
  131. }
  132.  
  133. bool wxTimerBase::Start(int milliseconds, bool oneShot)
  134. {
  135.     // under MSW timers only work when they're started from the main thread so
  136.     // let the caller know about it
  137. #if wxUSE_THREADS
  138.     wxASSERT_MSG( wxThread::IsMain(),
  139.                   _T("timer can only be started from the main thread") );
  140. #endif // wxUSE_THREADS
  141.  
  142.     if ( IsRunning() )
  143.     {
  144.         // not stopping the already running timer might work for some
  145.         // platforms (no problems under MSW) but leads to mysterious crashes
  146.         // on the others (GTK), so to be on the safe side do it here
  147.         Stop();
  148.     }
  149.  
  150.     if ( milliseconds != -1 )
  151.     {
  152.         m_milli = milliseconds;
  153.     }
  154.  
  155.     m_oneShot = oneShot;
  156.  
  157.     return TRUE;
  158. }
  159.  
  160. #endif // wxUSE_GUI
  161.  
  162. // ----------------------------------------------------------------------------
  163. // wxStopWatch
  164. // ----------------------------------------------------------------------------
  165.  
  166. #if wxUSE_LONGLONG
  167.  
  168. void wxStopWatch::Start(long t)
  169. {
  170.     m_t0 = wxGetLocalTimeMillis() - t;
  171.     m_pause = 0;
  172. }
  173.  
  174. long wxStopWatch::GetElapsedTime() const
  175. {
  176.     return (wxGetLocalTimeMillis() - m_t0).GetLo();
  177. }
  178.  
  179. long wxStopWatch::Time() const
  180. {
  181.     return m_pauseCount ? m_pause : GetElapsedTime();
  182. }
  183.  
  184. #endif // wxUSE_LONGLONG
  185.  
  186. // ----------------------------------------------------------------------------
  187. // old timer functions superceded by wxStopWatch
  188. // ----------------------------------------------------------------------------
  189.  
  190. #if wxUSE_LONGLONG
  191.  
  192. static wxLongLong wxStartTime = 0l;
  193.  
  194. // starts the global timer
  195. void wxStartTimer()
  196. {
  197.     wxStartTime = wxGetLocalTimeMillis();
  198. }
  199.  
  200. // Returns elapsed time in milliseconds
  201. long wxGetElapsedTime(bool resetTimer)
  202. {
  203.     wxLongLong oldTime = wxStartTime;
  204.     wxLongLong newTime = wxGetLocalTimeMillis();
  205.  
  206.     if ( resetTimer )
  207.         wxStartTime = newTime;
  208.  
  209.     return (newTime - oldTime).GetLo();
  210. }
  211.  
  212. #endif // wxUSE_LONGLONG
  213.  
  214. // ----------------------------------------------------------------------------
  215. // the functions to get the current time and timezone info
  216. // ----------------------------------------------------------------------------
  217.  
  218. // Get local time as seconds since 00:00:00, Jan 1st 1970
  219. long wxGetLocalTime()
  220. {
  221.     struct tm tm;
  222.     time_t t0, t1;
  223.  
  224.     // This cannot be made static because mktime can overwrite it.
  225.     //
  226.     memset(&tm, 0, sizeof(tm));
  227.     tm.tm_year  = 70;
  228.     tm.tm_mon   = 0;
  229.     tm.tm_mday  = 5;        // not Jan 1st 1970 due to mktime 'feature'
  230.     tm.tm_hour  = 0;
  231.     tm.tm_min   = 0;
  232.     tm.tm_sec   = 0;
  233.     tm.tm_isdst = -1;       // let mktime guess
  234.  
  235.     // Note that mktime assumes that the struct tm contains local time.
  236.     //
  237.     t1 = time(&t1);         // now
  238.     t0 = mktime(&tm);       // origin
  239.  
  240.     // Return the difference in seconds.
  241.     //
  242.     if (( t0 != (time_t)-1 ) && ( t1 != (time_t)-1 ))
  243.         return (long)difftime(t1, t0) + (60 * 60 * 24 * 4);
  244.  
  245.     wxLogSysError(_("Failed to get the local system time"));
  246.     return -1;
  247. }
  248.  
  249. // Get UTC time as seconds since 00:00:00, Jan 1st 1970
  250. long wxGetUTCTime()
  251. {
  252.     struct tm tm;
  253.     struct tm *ptm;
  254.     time_t t0, t1;
  255.  
  256.     // This cannot be made static because mktime can overwrite it
  257.     //
  258.     memset(&tm, 0, sizeof(tm));
  259.     tm.tm_year  = 70;
  260.     tm.tm_mon   = 0;
  261.     tm.tm_mday  = 5;        // not Jan 1st 1970 due to mktime 'feature'
  262.     tm.tm_hour  = 0;
  263.     tm.tm_min   = 0;
  264.     tm.tm_sec   = 0;
  265.     tm.tm_isdst = -1;       // let mktime guess
  266.  
  267.     // Note that mktime assumes that the struct tm contains local time.
  268.     //
  269.     t1 = time(&t1);         // now
  270.     t0 = mktime(&tm);       // origin in localtime
  271.  
  272.     if (( t0 != (time_t)-1 ) && ( t1 != (time_t)-1 ))
  273.     {
  274.         // To get t0 as GMT we convert to a struct tm with gmtime,
  275.         // and then back again.
  276.         //
  277.         ptm = gmtime(&t0);
  278.  
  279.         if (ptm)
  280.         {
  281.             memcpy(&tm, ptm, sizeof(tm));
  282.             t0 = mktime(&tm);
  283.  
  284.             if (t0 != (time_t)-1 )
  285.                 return (long)difftime(t1, t0) + (60 * 60 * 24 * 4);
  286.             wxLogSysError(_("mktime() failed"));
  287.         }
  288.         else
  289.         {
  290.             wxLogSysError(_("gmtime() failed"));
  291.         }
  292.     }
  293.  
  294.     wxLogError(_("Failed to get the UTC system time."));
  295.  
  296.     return -1;
  297. }
  298.  
  299. #if wxUSE_LONGLONG
  300.  
  301. // Get local time as milliseconds since 00:00:00, Jan 1st 1970
  302. wxLongLong wxGetLocalTimeMillis()
  303. {
  304.     wxLongLong val = 1000l;
  305.  
  306.     // If possible, use a function which avoids conversions from
  307.     // broken-up time structures to milliseconds
  308.  
  309. #if defined(__WXMSW__) && defined(__MWERKS__)
  310.     // This should probably be the way all WXMSW compilers should do it
  311.     // Go direct to the OS for time
  312.  
  313.     SYSTEMTIME thenst = { 1970, 1, 4, 1, 0, 0, 0, 0 };  // 00:00:00 Jan 1st 1970
  314.     FILETIME thenft;
  315.     SystemTimeToFileTime( &thenst, &thenft );
  316.     wxLongLong then( thenft.dwHighDateTime, thenft.dwLowDateTime );   // time in 100 nanoseconds
  317.  
  318.     SYSTEMTIME nowst;
  319.     GetLocalTime( &nowst );
  320.     FILETIME nowft;
  321.     SystemTimeToFileTime( &nowst, &nowft );
  322.     wxLongLong now( nowft.dwHighDateTime, nowft.dwLowDateTime );   // time in 100 nanoseconds
  323.  
  324.     return ( now - then ) / 10000.0;  // time from 00:00:00 Jan 1st 1970 to now in milliseconds
  325.     
  326. #elif defined(HAVE_GETTIMEOFDAY)
  327.     struct timeval tp;
  328.     if ( wxGetTimeOfDay(&tp, (struct timezone *)NULL) != -1 )
  329.     {
  330.         val *= tp.tv_sec;
  331.         return (val + (tp.tv_usec / 1000));
  332.     }
  333.     else
  334.     {
  335.         wxLogError(_("wxGetTimeOfDay failed."));
  336.         return 0;
  337.     }
  338. #elif defined(HAVE_FTIME)
  339.     struct timeb tp;
  340.  
  341.     // ftime() is void and not int in some mingw32 headers, so don't
  342.     // test the return code (well, it shouldn't fail anyhow...)
  343.     (void)ftime(&tp);
  344.     val *= tp.time;
  345.     return (val + tp.millitm);
  346. #elif defined(__WXMAC__)
  347.     
  348.     UInt64 gMilliAtStart = 0 ;
  349.     Nanoseconds upTime = AbsoluteToNanoseconds( UpTime() ) ;
  350.     if ( gMilliAtStart == 0 )
  351.     {
  352.         time_t start = time(NULL) ;
  353.         gMilliAtStart = ((UInt64) start) * 1000L ;
  354.         gMilliAtStart -= upTime.lo / 1000 ;
  355.         gMilliAtStart -= ( ( (UInt64) upTime.hi ) << 32 ) / 1000 ;
  356.     }
  357.     UInt64 millival = gMilliAtStart ;
  358.     millival += upTime.lo / 1000 ;
  359.     millival += ( ( (UInt64) upTime.hi ) << 32 ) / 1000 ;
  360.     val = millival ;
  361.     return val ;
  362. #else // no gettimeofday() nor ftime()
  363.     // We use wxGetLocalTime() to get the seconds since
  364.     // 00:00:00 Jan 1st 1970 and then whatever is available
  365.     // to get millisecond resolution.
  366.     //
  367.     // NOTE that this might lead to a problem if the clocks
  368.     // use different sources, so this approach should be
  369.     // avoided where possible.
  370.  
  371.     val *= wxGetLocalTime();
  372.  
  373. // GRG: This will go soon as all WIN32 seem to have ftime
  374. #if defined (__WIN32__)
  375.     // If your platform/compiler needs to use two different functions
  376.     // to get ms resolution, please do NOT just shut off these warnings,
  377.     // drop me a line instead at <guille@iies.es>
  378.     #warning "Possible clock skew bug in wxGetLocalTimeMillis()!"
  379.  
  380.     SYSTEMTIME st;
  381.     ::GetLocalTime(&st);
  382.     val += st.wMilliseconds;
  383. #else // !Win32
  384.     // If your platform/compiler does not support ms resolution please
  385.     // do NOT just shut off these warnings, drop me a line instead at
  386.     // <guille@iies.es>
  387.  
  388.     #if defined(__VISUALC__) || defined (__WATCOMC__)
  389.         #pragma message("wxStopWatch will be up to second resolution!")
  390.     #elif defined(__BORLANDC__)
  391.         #pragma message "wxStopWatch will be up to second resolution!"
  392.     #else
  393.         #warning "wxStopWatch will be up to second resolution!"
  394.     #endif // compiler
  395. #endif
  396.  
  397.     return val;
  398.  
  399. #endif // time functions
  400. }
  401.  
  402. #endif // wxUSE_LONGLONG
  403.  
  404.