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