Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/Time.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)1996 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: Time.cpp 1046 2004-02-27 19:20:16Z jungd $
00019   $Revision: 1.4 $
00020   $Date: 2004-02-27 14:20:16 -0500 (Fri, 27 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #include <base/Time>
00026 
00027 #include <base/Serializer>
00028 
00029 #include <iostream>
00030 
00031 extern "C" {
00032 #include <sys/time.h>
00033 #include <sys/uio.h>
00034 #include <unistd.h>
00035 #include <signal.h>
00036 }
00037 
00038 using base::Time;
00039 
00040 
00041 Time* Time::time=0;
00042 long Time::baseSecs;
00043 long Time::baseMicros;
00044 Time Time::lastNow;
00045 long Time::resolution;
00046 
00047 
00048 Time::Time()
00049 {
00050   const SInt minResolution = 20000; // 1/50th sec
00051   
00052   if (time==0) {
00053     // initialise statics
00054     time = this;
00055     
00056     /*
00057     // We use itimers to monitor passing time - but don't make use of signals for notification
00058     //  set the itimer SIGALRM to be ignored
00059     struct sigaction act;
00060     act.sa_handler = SIG_IGN;
00061     sigemptyset(&act.sa_mask);
00062     act.sa_flags=0;
00063     sigaction(SIGALRM, &act, 0);
00064     */
00065 
00066     // Get current system time to use as base (so the real-time starts at 0)
00067     struct timeval now;
00068     gettimeofday(&now,0);
00069     baseSecs = now.tv_sec;
00070     baseMicros = now.tv_usec;
00071 
00072     usleep(1);
00073     
00074     gettimeofday(&now,0);
00075     resolution = (now.tv_usec - baseMicros) + microsPerSec*(now.tv_sec - baseSecs);
00076 
00077     if (resolution > minResolution) {
00078       
00079       // it is possible the timer wrapped, so just do the calculation again, just in case
00080       gettimeofday(&now,0);
00081       baseSecs = now.tv_sec;
00082       baseMicros = now.tv_usec;
00083       usleep(1);
00084       
00085       gettimeofday(&now,0);
00086       resolution = (now.tv_usec - baseMicros) + microsPerSec*(now.tv_sec - baseSecs);
00087       
00088       if (resolution > minResolution) {   
00089         Logln("WARNING: time resolution is only " << resolution << "us.  It may be too coarse.");
00090       }
00091       
00092     }
00093     //Logln("Time resolution: " << resolution << "us ; " << (Real(resolution)/Real(1000000)) << "s" << " ; 1/" << 1.0/(Real(resolution)/Real(1000000)) << "th of a sec" );
00094   }
00095 
00096   secs=micros=0;
00097 }
00098 
00099 
00100 
00101 Time::Time(Real secs)
00102 {
00103   this->secs = long(secs);
00104   micros = long((secs-Real(this->secs))*Real(microsPerSec));
00105 }
00106 
00107 
00108 Time::~Time()
00109 {
00110   if (this==time) {
00111     // cleanup statics
00112 
00113     time=0;
00114   }
00115 }
00116 
00117 
00118 const Time& Time::now()
00119 {
00120   struct timeval now;
00121   gettimeofday(&now,0);
00122   lastNow.secs = now.tv_sec - baseSecs;
00123   lastNow.micros = now.tv_usec - baseMicros;
00124   if (lastNow.micros < 0) {
00125     lastNow.micros += microsPerSec;
00126     lastNow.secs--;
00127   }
00128   return lastNow;
00129 }
00130 
00131 
00132 bool Time::less(const Time& t1, const Time& t2)
00133 {
00134   if (t1.secs < t2.secs)
00135     return true;
00136   else
00137     if (t1.secs == t2.secs)
00138       return (t1.micros < t2.micros);
00139 
00140   return false;
00141 }
00142 
00143 
00144 bool Time::greater(const Time& t1, const Time& t2)
00145 {
00146   if (t1.secs > t2.secs)
00147     return true;
00148   else
00149     if (t1.secs == t2.secs)
00150       return (t1.micros > t2.micros);
00151 
00152   return false;
00153 }
00154 
00155 
00156 void Time::sleep(const Time& t)
00157 {
00158   if (t.secs > 0) ::sleep(t.secs);
00159   if (t.micros > 0) usleep(t.micros);
00160 }
00161 
00162 
00163 void Time::sleep(long secs, long micros)
00164 {
00165   sleep(Time(secs,micros));
00166 }
00167 
00168 
00169 void Time::normalize()
00170 {
00171   if (secs > 0) {
00172     while (micros < 0) {
00173       micros+= microsPerSec;
00174       secs--;
00175     }
00176     while (micros >= microsPerSec) {
00177       micros-= microsPerSec;
00178       secs++;
00179     }
00180   }
00181   
00182   if (secs == 0) {
00183     while (micros >= microsPerSec) {
00184       micros-= microsPerSec;
00185       secs++;
00186     }
00187     while (micros <= -microsPerSec) {
00188       micros+= microsPerSec;
00189       secs--;
00190     }
00191   }
00192 
00193   if (secs < 0) {
00194     while (micros > 0) {
00195       micros-= microsPerSec;
00196       secs++;
00197     }
00198     while (micros <= -microsPerSec) {
00199       micros+= microsPerSec;
00200       secs--;
00201     }
00202   }
00203 
00204   if (secs!=0) {
00205     if ((secs>0) && (micros<0)) {
00206       micros+=microsPerSec;
00207       secs--;
00208     }
00209     if ((secs<0) && (micros>0)) {
00210       micros-=microsPerSec;
00211       secs++;
00212     }
00213   }
00214 
00215 }
00216 
00217 
00218 std::ostream& base::operator<<(std::ostream& out, const Time& t)
00219 {
00220   return out << t.secs << "s:" << t.micros << "us";
00221 }
00222 
00223 
00224 Time& Time::operator-=(const Time& t)
00225 {
00226   long ds = secs - t.secs;
00227   long dm = micros - t.micros;
00228 
00229   Time r(ds,dm);
00230   r.normalize();
00231   *this = r;
00232   return *this;
00233 }
00234 
00235 
00236 Time& Time::operator+=(const Time& t)
00237 {
00238   long ss = secs + t.secs;
00239   long sm = micros + t.micros;
00240 
00241   Time r(ss,sm);
00242   r.normalize();
00243   *this = r;
00244   return *this;
00245 }
00246 
00247 
00248 Time& Time::operator*=(Real s)
00249 {
00250   Real rs = Real(secs)*s;
00251   long ss = long(rs);
00252   Real ds = rs - ss;
00253   
00254   long sm = long( Real(micros)*s );
00255   sm += long( ds*microsPerSec );
00256 
00257   Time r(ss,sm);
00258   r.normalize();
00259   *this = r;
00260   return *this;
00261 }
00262 
00263 
00264 void Time::serialize(Serializer& s)
00265 { 
00266   s(LInt(secs),"secs"); s(LInt(micros),"micros"); 
00267 }
00268 
00269 

Generated on Thu Jul 29 15:56:15 2004 for OpenSim by doxygen 1.3.6