Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/express/trueClock.cxx

Go to the documentation of this file.
00001 // Filename: trueClock.cxx
00002 // Created by:  drose (04Jul00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 
00020 #include "trueClock.h"
00021 #include "config_express.h"
00022 #include "numeric_types.h"
00023 
00024 #include "math.h"  // for fabs()
00025 
00026 TrueClock *TrueClock::_global_ptr = NULL;
00027 
00028 #if defined(WIN32_VC)
00029 
00030 ////////////////////////////////////////////////////////////////////
00031 //
00032 // The Win32 implementation.
00033 //
00034 ////////////////////////////////////////////////////////////////////
00035 
00036 #include <sys/timeb.h>
00037 
00038 #define WINDOWS_LEAN_AND_MEAN
00039 #include <windows.h>
00040 #undef WINDOWS_LEAN_AND_MEAN
00041 
00042 static BOOL _has_high_res;
00043 static PN_int64 _frequency;
00044 static PN_int64 _init_count;
00045 static double _fFrequency,_recip_fFrequency;
00046 static DWORD _init_tc;
00047 static bool _paranoid_clock;
00048 static const double _0001 = 1.0/1000.0;
00049 
00050 void get_true_time_of_day(ulong &sec, ulong &usec) {
00051   struct timeb tb;
00052   ftime(&tb);
00053   sec = tb.time;
00054   usec = (ulong)(tb.millitm * 1000.0);
00055 }
00056 
00057 double TrueClock::
00058 get_long_time() const {
00059   DWORD tc = GetTickCount();
00060   return (double)(tc - _init_tc) * _0001;
00061 }
00062 
00063 double TrueClock::
00064 get_short_time() const {
00065   if (_has_high_res) {
00066     LARGE_INTEGER count;
00067     QueryPerformanceCounter(&count);
00068 
00069     double time = (double)(count.QuadPart - _init_count) * _recip_fFrequency;
00070 
00071     if (_paranoid_clock) {
00072       // Now double-check the high-resolution clock against the system
00073       // clock.
00074       DWORD tc = GetTickCount();
00075       double sys_time = (double)(tc - _init_tc) * _0001;
00076       if (fabs(time - sys_time) > 0.5) {
00077         // Too much variance!
00078         express_cat.info()
00079           << "Clock error!  High resolution clock reads " << time 
00080           << " while system clock reads " << sys_time << ".\n";
00081         _init_count = 
00082           (PN_int64)(count.QuadPart - sys_time * _fFrequency);
00083         time = (double)(count.QuadPart - _init_count) * _recip_fFrequency;
00084         express_cat.info()
00085           << "High resolution clock reset to " << time << ".\n";
00086       }
00087     }
00088 
00089     return time;
00090 
00091   } else {
00092     // No high-resolution clock; return the best information we have.
00093     DWORD tc = GetTickCount();
00094     return (double)(tc - _init_tc) * _0001;
00095   }
00096 }
00097 
00098 TrueClock::
00099 TrueClock() {
00100   _has_high_res = false;
00101   if (get_use_high_res_clock()) {
00102     _has_high_res = QueryPerformanceFrequency((LARGE_INTEGER *)&_frequency);
00103     _fFrequency = (double) _frequency;
00104     _recip_fFrequency = 1.0/_fFrequency;
00105   }
00106 
00107   _paranoid_clock = get_paranoid_clock();
00108 
00109   if (_has_high_res) {
00110     LARGE_INTEGER count;
00111     QueryPerformanceCounter(&count);
00112     _init_count = count.QuadPart;
00113 
00114     if (_frequency <= 0) {
00115       express_cat.error()
00116         << "TrueClock::get_real_time() - frequency is negative!" << endl;
00117       _has_high_res = false;
00118     }
00119   }
00120 
00121   // Also store the initial tick count.  We'll need this for
00122   // get_long_time(), as well as for get_short_time() if we're not
00123   // using the high resolution clock, or to cross-check the high
00124   // resolution clock if we are using it.
00125   _init_tc = GetTickCount();
00126 
00127   if (!_has_high_res) {
00128     express_cat.warning()
00129       << "No high resolution clock available." << endl;
00130 
00131   } else if (_paranoid_clock) {
00132     express_cat.info()
00133       << "Not trusting the high resolution clock." << endl;
00134   }
00135 }
00136 
00137 
00138 #elif defined(PENV_PS2)
00139 
00140 ////////////////////////////////////////////////////////////////////
00141 //
00142 // The PS2 implementation.
00143 //
00144 ////////////////////////////////////////////////////////////////////
00145 
00146 
00147 #include <eeregs.h>
00148 #include <eekernel.h>
00149 
00150 static unsigned int _msec;
00151 static unsigned int _sec;
00152 
00153 // PS2 timer interrupt, as the RTC routines don't exist unless you're
00154 // using the .irx iop compiler, which scares us.  A lot.
00155 static int
00156 timer_handler(int) {
00157   _msec++;
00158 
00159   if (_msec >= 1000) {
00160     _msec = 0;
00161     _sec++;
00162   }
00163 
00164   return -1;
00165 }
00166 
00167 void get_true_time_of_day(ulong &sec, ulong &msec) {
00168   cerr << "get_true_time_of_day() not implemented!" << endl;
00169 }
00170 
00171 double TrueClock::
00172 get_long_time() const {
00173   return (double) _sec + ((double) _msec / 1000.0);
00174 }
00175 
00176 double TrueClock::
00177 get_short_time() const {
00178   return (double) _sec + ((double) _msec / 1000.0);
00179 }
00180 
00181 TrueClock::
00182 TrueClock() {
00183   _init_sec = 0;
00184   _msec = 0;
00185   _sec = 0;
00186 
00187   tT_MODE timer_mode;
00188   *(unsigned int *) &timer_mode = 0;
00189 
00190   timer_mode.cxxLKS = 1;
00191   timer_mode.ZRET = 1;
00192   timer_mode.cxxUE = 1;
00193   timer_mode.cxxMPE = 1;
00194   timer_mode.EQUF = 1;
00195 
00196   *T0_COMP = 9375;
00197   *T0_MODE = *(unsigned int *) &timer_mode;
00198 
00199   EnableIntc(INTC_TIM0);
00200   AddIntcHandler(INTC_TIM0, timer_handler, -1);
00201 }
00202 
00203 
00204 #elif !defined(WIN32_VC)
00205 
00206 ////////////////////////////////////////////////////////////////////
00207 //
00208 // The Posix implementation.
00209 //
00210 ////////////////////////////////////////////////////////////////////
00211 
00212 #include <sys/time.h>
00213 #include <stdio.h>  // for perror
00214 
00215 static long _init_sec;
00216 
00217 void get_true_time_of_day(ulong &sec, ulong &msec) {
00218   struct timeval tv;
00219   int result;
00220 
00221 #ifdef GETTIMEOFDAY_ONE_PARAM
00222   result = gettimeofday(&tv);
00223 #else
00224   result = gettimeofday(&tv, (struct timezone *)NULL);
00225 #endif
00226 
00227   if (result < 0) {
00228     sec = 0;
00229     msec = 0;
00230     // Error in gettimeofday().
00231     return;
00232   }
00233   sec = tv.tv_sec;
00234   msec = tv.tv_usec;
00235 }
00236 
00237 double TrueClock::
00238 get_long_time() const {
00239   struct timeval tv;
00240 
00241   int result;
00242 
00243 #ifdef GETTIMEOFDAY_ONE_PARAM
00244   result = gettimeofday(&tv);
00245 #else
00246   result = gettimeofday(&tv, (struct timezone *)NULL);
00247 #endif
00248 
00249   if (result < 0) {
00250     // Error in gettimeofday().
00251     return 0.0;
00252   }
00253 
00254   // We subtract out the time at which the clock was initialized,
00255   // because we don't care about the number of seconds all the way
00256   // back to 1970, and we want to leave the double with as much
00257   // precision as it can get.
00258   return (double)(tv.tv_sec - _init_sec) + (double)tv.tv_usec / 1000000.0;
00259 }
00260 
00261 double TrueClock::
00262 get_short_time() const {
00263   struct timeval tv;
00264 
00265   int result;
00266 
00267 #ifdef GETTIMEOFDAY_ONE_PARAM
00268   result = gettimeofday(&tv);
00269 #else
00270   result = gettimeofday(&tv, (struct timezone *)NULL);
00271 #endif
00272 
00273   if (result < 0) {
00274     // Error in gettimeofday().
00275     return 0.0;
00276   }
00277 
00278   // We subtract out the time at which the clock was initialized,
00279   // because we don't care about the number of seconds all the way
00280   // back to 1970, and we want to leave the double with as much
00281   // precision as it can get.
00282   return (double)(tv.tv_sec - _init_sec) + (double)tv.tv_usec / 1000000.0;
00283 }
00284 
00285 TrueClock::
00286 TrueClock() {
00287   struct timeval tv;
00288 
00289   int result;
00290 #ifdef GETTIMEOFDAY_ONE_PARAM
00291   result = gettimeofday(&tv);
00292 #else
00293   result = gettimeofday(&tv, (struct timezone *)NULL);
00294 #endif
00295 
00296   if (result < 0) {
00297     perror("gettimeofday");
00298     _init_sec = 0;
00299   } else {
00300     _init_sec = tv.tv_sec;
00301   }
00302 }
00303 
00304 #endif

Generated on Fri May 2 00:38:42 2003 for Panda by doxygen1.3