Fawkes API
Fawkes Development Version
|
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