time.cpp

00001 
00002 /***************************************************************************
00003  *  time.c - A time class
00004  *
00005  *  Created: Wed Jun 06 16:50:11 2007
00006  *  Copyright  2007       Daniel Beck
00007  *             2007-2009  Tim Niemueller [www.niemueller.de]
00008  *
00009  ****************************************************************************/
00010 
00011 /*  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version. A runtime exception applies to
00015  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00016  *
00017  *  This program is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  *  GNU Library General Public License for more details.
00021  *
00022  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00023  */
00024 
00025 #include <utils/time/time.h>
00026 #include <utils/time/clock.h>
00027 
00028 #include <core/exception.h>
00029 #include <core/exceptions/software.h>
00030 
00031 #include <time.h>
00032 #include <cmath>
00033 #include <cstdio>
00034 #include <cstdlib>
00035 #include <cstring>
00036 #include <unistd.h>
00037 
00038 namespace fawkes {
00039 #if 0 /* just to make Emacs auto-indent happy */
00040 }
00041 #endif
00042 
00043 /** @class Time <utils/time/time.h>
00044  * A class for handling time.
00045  * @author Daniel Beck
00046  * @author Tim Niemueller
00047  *
00048  * @fn const timeval * Time::get_timeval() const
00049  * Obtain the timeval where the time is stored.
00050  * @return a const pointer to the timeval where the time is stored
00051  *
00052  * @fn long Time::get_sec() const
00053  * Get seconds.
00054  * @return seconds stored in time stamp
00055  *
00056  * @fn long Time::get_msec() const
00057  * Get milliseconds.
00058  * @return milliseconds stored in time stamp
00059  *
00060  * @fn long Time::get_usec() const
00061  * Get microseconds.
00062  * @return microseconds stored in time stamp
00063  *
00064  * @fn void Time::get_timestamp(long &sec, long &usec) const
00065  * Get time stamp.
00066  * @param sec upon return contains seconds stored in time stamp
00067  * @param usec upon return contains microseconds stored in time stamp
00068  */
00069 
00070 /** Maximum size of string returned by str() and the minimum size
00071  * of the string passwd to str_r(). */
00072 // as recommened in asctime_r() docs
00073 const unsigned int Time::TIMESTR_SIZE = 26;
00074 
00075 
00076 /** Constructor.
00077  * Sets time to the current time.
00078  */
00079 Time::Time()
00080 {
00081   __clock = Clock::instance();
00082   __clock->get_time(&__time);
00083   __timestr = NULL;
00084 }
00085 
00086 
00087 /** Constructor.
00088  * Sets time to the given time.
00089  * @param tv the Time object is initialized with the time given in this timeval
00090  */
00091 Time::Time(const timeval* tv)
00092 {
00093   __time.tv_sec = tv->tv_sec;
00094   __time.tv_usec = tv->tv_usec;
00095   __clock = Clock::instance();
00096   __timestr = NULL;
00097 }
00098 
00099 
00100 /** Constructor.
00101  * Sets time to the given time. Basically the same as setting from a timeval struct
00102  * but the components are given separately.
00103  * @param sec time in seconds since the epoch (or time range)
00104  * @param usec fractions in microseconds added to sec
00105  * @param clock optional clock to use, if NULL Clock::instance() will be used
00106  */
00107 Time::Time(long sec, long usec, Clock *clock)
00108 {
00109   __time.tv_sec  = sec;
00110   __time.tv_usec = usec;
00111   if (clock) {
00112     __clock = clock;
00113   } else {
00114     __clock = Clock::instance();
00115   }
00116   __timestr = NULL;
00117 }
00118 
00119 
00120 /** Constructor.
00121  * Sets time to given number of ms, use for time range.
00122  * @param ms the Time object is initialized to the time given in milli-seconds
00123  */
00124 Time::Time(long ms)
00125 {
00126   time_t sec = (time_t) (ms / 1000.0);
00127   suseconds_t usec =  (ms % 1000) * 1000;
00128 
00129   __time.tv_sec = sec;
00130   __time.tv_usec = usec;
00131   __clock = Clock::instance();
00132   __timestr = NULL;
00133 }
00134 
00135 
00136 /** Constructor.
00137  * Sets time to given number of ms, use for time range.
00138  * @param s the Time object is initialized to the time given in seconds
00139  */
00140 Time::Time(float s)
00141 {
00142   time_t sec = (time_t) s;
00143   suseconds_t usec = (suseconds_t)roundf((s - sec) * 1000000.f);
00144 
00145   __time.tv_sec = sec;
00146   __time.tv_usec = usec;
00147   __clock = Clock::instance();
00148   __timestr = NULL;
00149 }
00150 
00151 
00152 /** Constructor.
00153  * This constructor uses the supplied clock for setting the time. The
00154  * time is set to the current time.
00155  * @param clock clock
00156  */
00157 Time::Time(Clock *clock)
00158 {
00159   this->__clock = clock;
00160   __clock->get_time(&__time);
00161   __timestr = NULL;
00162 }
00163 
00164 
00165 /** Copy constructor.
00166  * @param t time to copy
00167  */
00168 Time::Time(const Time &t)
00169 {
00170   __time.tv_sec  = t.__time.tv_sec;
00171   __time.tv_usec = t.__time.tv_usec;
00172   __clock        = t.__clock;
00173   if (t.__timestr) {
00174     __timestr = (char *)malloc(TIMESTR_SIZE);
00175     strncpy(__timestr, t.__timestr, TIMESTR_SIZE);
00176   } else {
00177     __timestr = NULL;
00178   }
00179 }
00180 
00181 
00182 /** Copy constructor.
00183  * @param t time to copy
00184  */
00185 Time::Time(const Time *t)
00186 {
00187   __time.tv_sec  = t->__time.tv_sec;
00188   __time.tv_usec = t->__time.tv_usec;
00189   __clock        = t->__clock;
00190   if (t->__timestr) {
00191     __timestr = (char *)malloc(TIMESTR_SIZE);
00192     strncpy(__timestr, t->__timestr, TIMESTR_SIZE);
00193   } else {
00194     __timestr = NULL;
00195   }
00196 }
00197 
00198 
00199 /** Destructor. */
00200 Time::~Time()
00201 {
00202   if (__timestr)  free(__timestr);
00203 }
00204 
00205 
00206 /** Convet time to seconds.
00207  * Convert the stored time in a floating point number representing the
00208  * number of seconds. For a time the integral part is the number of seconds
00209  * since the epoch, for ranges you get the value as a float second.
00210  * @return the time in seconds
00211  */
00212 float
00213 Time::in_sec() const
00214 {
00215   return (__time.tv_sec + __time.tv_usec / 1000000.f);
00216 }
00217 
00218 
00219 /** Convert the stored time into milli-seconds.
00220  * @return the time in milli-seconds
00221  */
00222 long
00223 Time::in_msec() const
00224 {
00225   return (__time.tv_sec * 1000 + (long) (__time.tv_usec / 1000));
00226 }
00227 
00228 
00229 /** Convert the stored time into micro-seconds.
00230  * @return the time in micro-seconds
00231  */
00232 long
00233 Time::in_usec() const
00234 {
00235   return (__time.tv_sec * 1000000 + __time.tv_usec);
00236 }
00237 
00238 
00239 /** Sets the time.
00240  * @param tv set the time to this value
00241  */
00242 void
00243 Time::set_time(const timeval* tv)
00244 {
00245   __time.tv_sec = tv->tv_sec;
00246   __time.tv_usec = tv->tv_usec;
00247 }
00248 
00249 
00250 /** Sets the time.
00251  * @param sec seconds part of the time
00252  * @param usec microseconds part of the time
00253  */
00254 void
00255 Time::set_time(long int sec, long int usec)
00256 {
00257   __time.tv_sec  = sec;
00258   __time.tv_usec = usec;
00259 }
00260 
00261 
00262 /** Sets the time.
00263  * @param ms set the time to this value
00264  */
00265 void
00266 Time::set_time(long ms)
00267 {
00268   __time.tv_sec  = (time_t) (ms / 1000.0);
00269   __time.tv_usec = (ms % 1000) * 1000;
00270 }
00271 
00272 
00273 /** Sets the time.
00274  * @param s set the time to this value
00275  */
00276 void
00277 Time::set_time(float s)
00278 {
00279   __time.tv_sec  = (time_t)floor(s);
00280   __time.tv_usec = (suseconds_t)(s - __time.tv_sec) * 1000000;
00281 }
00282 
00283 /** Set time to given time.
00284  * this is equivalent to operator+, but can be used in situations where
00285  * the operator cannot be used (for example in Lua).
00286  * @param t time to set to
00287  */
00288 void
00289 Time::set_time(const Time &t)
00290 {
00291   *this = t;
00292 }
00293 
00294 
00295 /** Set time to given time.
00296  * @param t time to set to
00297  */
00298 void
00299 Time::set_time(const Time *t)
00300 {
00301   __time.tv_sec  = t->__time.tv_sec;
00302   __time.tv_usec = t->__time.tv_usec;
00303 }
00304 
00305 
00306 /** Set clock for this instance.
00307  * @param clock clock to use from now on
00308  */
00309 void
00310 Time::set_clock(Clock *clock)
00311 {
00312   if (clock == NULL) throw NullPointerException("Clock may not be NULL");
00313   __clock = clock;
00314 }
00315 
00316 
00317 /** Add seconds.
00318  * The effect is equivalent to operator+=(const float sec), but this
00319  * can be used when the operator is not available (i.e. wrapper languages)
00320  * and it does not return itself.
00321  * @param seconds time in seconds to add
00322  */
00323 void
00324 Time::add(float seconds)
00325 {
00326   *this += seconds;
00327 }
00328 
00329 /** Operator that adds times.
00330  * @param t the other summand
00331  * @return the sum
00332  */
00333 Time
00334 Time::operator+(const Time& t) const
00335 {
00336   Time ret;
00337   if (__time.tv_usec + t.__time.tv_usec >= 1000000)
00338   {
00339     ret.__time.tv_usec = __time.tv_usec + t.__time.tv_usec - 1000000;
00340     ret.__time.tv_sec = __time.tv_sec + t.__time.tv_sec + 1;
00341   }
00342   else
00343   {
00344     ret.__time.tv_usec = __time.tv_usec + t.__time.tv_usec;
00345     ret.__time.tv_sec = __time.tv_sec + t.__time.tv_sec;
00346   }
00347 
00348   return ret;
00349 }
00350 
00351 
00352 /** Operator that adds times.
00353  * @param t the other summand
00354  * @return the sum
00355  */
00356 Time
00357 Time::operator+(const Time* t) const
00358 {
00359   return *this + *t;
00360 }
00361 
00362 
00363 /** Operator that adds times.
00364  * @param sec number of seconds to add
00365  * @return the sum
00366  */
00367 Time
00368 Time::operator+(const float sec) const
00369 {
00370   Time ret;
00371   time_t sec_only = (time_t)floor(sec);
00372   suseconds_t usec_only = (suseconds_t)roundf((sec - sec_only) * 1000000);
00373   if ((__time.tv_usec + usec_only) >= 1000000)
00374   {
00375     ret.__time.tv_usec = __time.tv_usec + usec_only - 1000000;
00376     ret.__time.tv_sec = __time.tv_sec + sec_only + 1;
00377   }
00378   else
00379   {
00380     ret.__time.tv_usec = __time.tv_usec + usec_only;
00381     ret.__time.tv_sec = __time.tv_sec + sec_only;
00382   }
00383 
00384   return ret;
00385 }
00386 
00387 
00388 /** Operator that substracts one Time from another.
00389  * @param t the Time that is substracted
00390  * @return the difference
00391  */
00392 Time
00393 Time::operator-(const Time& t) const
00394 {
00395   Time ret;
00396   if (__time.tv_usec < t.__time.tv_usec)
00397   {
00398     ret.__time.tv_usec = 1000000 + __time.tv_usec - t.__time.tv_usec;
00399     ret.__time.tv_sec = __time.tv_sec - t.__time.tv_sec - 1;
00400   }
00401   else
00402   {
00403     ret.__time.tv_usec = __time.tv_usec - t.__time.tv_usec;
00404     ret.__time.tv_sec = __time.tv_sec - t.__time.tv_sec;
00405   }
00406 
00407   return ret;
00408 }
00409 
00410 
00411 /** Operator that substracts one Time from another.
00412  * @param t the Time that is substracted
00413  * @return the difference
00414  */
00415 float
00416 Time::operator-(const Time* t) const
00417 {
00418   return time_diff_sec(__time, t->__time);
00419 }
00420 
00421 
00422 /** += operator
00423  * @param t the other time
00424  * @return reference to this instance
00425  */
00426 Time &
00427 Time::operator+=(const Time& t)
00428 {
00429   if (__time.tv_usec + t.__time.tv_usec >= 1000000)
00430   {
00431     __time.tv_usec += t.__time.tv_usec - 1000000;
00432     __time.tv_sec  += t.__time.tv_sec + 1;
00433   }
00434   else
00435   {
00436     __time.tv_usec += t.__time.tv_usec;
00437     __time.tv_sec  += t.__time.tv_sec;
00438   }
00439 
00440   return *this;
00441 }
00442 
00443 
00444 /** += operator
00445  * @param usec microseconds to add
00446  * @return reference to this instance
00447  */
00448 Time &
00449 Time::operator+=(const long int usec)
00450 {
00451   if ( __time.tv_usec + usec >= 1000000 )
00452   {
00453     //usec + __time.tv_usec might be more than 1 second
00454     long int tmp_usec = __time.tv_usec + usec;
00455     __time.tv_usec = tmp_usec % 1000000;
00456     __time.tv_sec  += tmp_usec / 1000000;
00457   }
00458   else
00459   {
00460     __time.tv_usec += usec;
00461   }
00462 
00463   return *this;
00464 }
00465 
00466 
00467 /** += operator for float seconds
00468  * @param sec number of seconds to add
00469  * @return the sum
00470  */
00471 Time &
00472 Time::operator+=(const float sec)
00473 {
00474   time_t sec_only = (time_t)floor(sec);
00475   suseconds_t usec_only = (suseconds_t)roundf((sec - sec_only) * 1000000);
00476   if ((__time.tv_usec + usec_only) >= 1000000)
00477   {
00478     __time.tv_usec += usec_only - 1000000;
00479     __time.tv_sec  += sec_only + 1;
00480   }
00481   else
00482   {
00483     __time.tv_usec += usec_only;
00484     __time.tv_sec  += sec_only;
00485   }
00486 
00487   return *this;
00488 }
00489 
00490 
00491 /** -= operator.
00492  * @param t the other time
00493  * @return reference to this instance
00494  */
00495 Time &
00496 Time::operator-=(const Time& t)
00497 {
00498   *this = *this - t;
00499   return *this;
00500 }
00501 
00502 
00503 /** Assign operator.
00504  * @param t time to assign to this instance
00505  * @return reference to this instance
00506  */
00507 Time &
00508 Time::operator=(const Time &t)
00509 {
00510   __time.tv_sec  = t.__time.tv_sec;
00511   __time.tv_usec = t.__time.tv_usec;
00512   __clock        = t.__clock;
00513   return *this;
00514 }
00515 
00516 
00517 /** Check equality of times.
00518  * @param t time to compare to
00519  * @return true if sec and usec of both times are the same, false otherwise
00520  */
00521 bool
00522 Time::operator==(const Time& t) const
00523 {
00524   return (__time.tv_sec == t.__time.tv_sec) &&
00525          (__time.tv_usec == t.__time.tv_usec);
00526 }
00527 
00528 
00529 /** Check equality of times.
00530  * @param t time to compare to
00531  * @return true if sec and usec of both times are the same, false otherwise
00532  */
00533 bool
00534 Time::operator==(const Time* t) const
00535 {
00536   return (__time.tv_sec == t->__time.tv_sec) &&
00537          (__time.tv_usec == t->__time.tv_usec);
00538 }
00539 
00540 
00541 /** Check inequality of times.
00542  * @param t time to compare to
00543  * @return true if sec or usec of both times are different, false otherwise
00544  */
00545 bool
00546 Time::operator!=(const Time& t) const
00547 {
00548   return (__time.tv_sec != t.__time.tv_sec) ||
00549          (__time.tv_usec != t.__time.tv_usec);
00550 }
00551 
00552 
00553 /** Check inequality of times.
00554  * @param t time to compare to
00555  * @return true if sec or usec of both times are different, false otherwise
00556  */
00557 bool
00558 Time::operator!=(const Time* t) const
00559 {
00560   return (__time.tv_sec != t->__time.tv_sec) ||
00561          (__time.tv_usec != t->__time.tv_usec);
00562 }
00563 
00564 
00565 /** Set this time to the current time.
00566  * @return reference to this instance
00567  */
00568 Time &
00569 Time::stamp()
00570 {
00571   if ( NULL != __clock ) {
00572     __clock->get_time(&__time);
00573   } else {
00574     throw Exception("Clock not set, cannot stamp time");
00575   }
00576   return *this;
00577 }
00578 
00579 
00580 /** Set this time to the current system time.
00581  * This bypasses any possibly registered time source. Use with care and only
00582  * where you really need the system time.
00583  * @return reference to this instance
00584  */
00585 Time &
00586 Time::stamp_systime()
00587 {
00588   if ( NULL != __clock ) {
00589     __clock->get_systime(&__time);
00590   } else {
00591     throw Exception("Clock not set, cannot stamp time (systime)");
00592   }
00593   return *this;
00594 }
00595 
00596 
00597 /** Wait (sleep) for this time.
00598  * This waits for as much time as this instance provides. Note that you have to
00599  * make sure that you call this on a sensible time range. You probably do not want
00600  * to wait for almost 40 years when passing a time point...
00601  */
00602 void
00603 Time::wait()
00604 {
00605   Time until, now;
00606   until += *this;
00607 
00608   // we want to release run status at least shortly
00609   usleep(0);
00610 
00611   long int remaining_usec = (until - now).in_usec();
00612   while ( remaining_usec > 0 ) {
00613     usleep(remaining_usec);
00614     now.stamp();
00615     remaining_usec = (until - now).in_usec();
00616   }
00617 }
00618 
00619 
00620 /** Wait (sleep) for this system time.
00621  * This waits for as much time as this instance provides. Unlike wait() this
00622  * method calculates the time in system time, althouh the main clock may run
00623  * slower for example in a simulation. Note that you have to make sure that you
00624  * call this on a sensible time range. You probably do not want to wait for
00625  * almost 40 years when passing a time point...
00626  */
00627 void
00628 Time::wait_systime()
00629 {
00630   Time until, now;
00631 
00632   __clock->get_systime(until);
00633   until += *this;
00634 
00635   __clock->get_systime(now);
00636 
00637   // we want to release run status at least shortly
00638   usleep(0);
00639 
00640   long int remaining_usec = (until - now).in_usec();
00641   while ( remaining_usec > 0 ) {
00642     usleep(remaining_usec);
00643     __clock->get_systime(now);
00644     remaining_usec = (until - now).in_usec();
00645   }
00646 }
00647 
00648 /** Output function.
00649  * @return a pointer to a member containing a string represenation of
00650  * the given time. If seconds is smaller than 1 billion it is assumed that
00651  * this time represents a time range rather than a point in time and
00652  * the time is formatted as seconds.microseconds, otherwise the time
00653  * is formatted either via localtime() (if utc is false) or gmtime (if utc
00654  * is true).
00655  * @param utc true to get type formatted in UTC, otherwise local time
00656  */
00657 const char *
00658 Time::str(bool utc) const
00659 {
00660   // allocate time string if not done yet
00661   if ( ! __timestr )  __timestr = (char *)malloc(TIMESTR_SIZE);
00662 
00663   // heuristic to distinguish times and time ranges
00664   if (__time.tv_sec < 1000000000) {
00665 #ifdef __FreeBSD__
00666     snprintf(__timestr, TIMESTR_SIZE, "%i:%li", __time.tv_sec, __time.tv_usec);
00667 #else
00668     snprintf(__timestr, TIMESTR_SIZE, "%li:%li", __time.tv_sec, __time.tv_usec);
00669 #endif
00670   } else {
00671     tm time_tm;
00672     if ( utc ) {
00673       gmtime_r( &(__time.tv_sec), &time_tm );
00674     } else {
00675       localtime_r( &(__time.tv_sec), &time_tm );
00676     }
00677     asctime_r(&time_tm, __timestr);
00678     __timestr[strlen(__timestr) - 1] = 0;
00679   }
00680 
00681   return __timestr;
00682 }
00683 
00684 
00685 /** Output function.
00686  * This is the thread-safe version of str().
00687  * @param s pointer to a string of at least TIMESTR_SIZE bytes.
00688  * @param utc true to get type formatted in UTC, otherwise local time
00689  */
00690 void
00691 Time::str_r(char *s, bool utc)
00692 {
00693   // heuristic to distinguish times and time ranges
00694   if (__time.tv_sec < 1000000000) {
00695 #ifdef __FreeBSD__
00696     snprintf(s, TIMESTR_SIZE, "%i:%li", __time.tv_sec, __time.tv_usec);
00697 #else
00698     snprintf(s, TIMESTR_SIZE, "%li:%li", __time.tv_sec, __time.tv_usec);
00699 #endif
00700   } else {
00701     tm time_tm;
00702     if ( utc ) {
00703       gmtime_r( &(__time.tv_sec), &time_tm );
00704     } else {
00705       localtime_r( &(__time.tv_sec), &time_tm );
00706     }
00707     asctime_r(&time_tm, s);
00708     s[strlen(s) - 1] = 0;
00709   }
00710 }
00711 
00712 } // end namespace fawkes

Generated on Tue Feb 22 13:32:29 2011 for Fawkes API by  doxygen 1.4.7