xorp

timeval.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 // vim:set sts=4 ts=8:
00003 
00004 // Copyright (c) 2001-2011 XORP, Inc and Others
00005 //
00006 // This program is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU Lesser General Public License, Version
00008 // 2.1, June 1999 as published by the Free Software Foundation.
00009 // Redistribution and/or modification of this program under the terms of
00010 // any other version of the GNU Lesser General Public License is not
00011 // permitted.
00012 // 
00013 // This program is distributed in the hope that it will be useful, but
00014 // WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00016 // see the GNU Lesser General Public License, Version 2.1, a copy of
00017 // which can be found in the XORP LICENSE.lgpl file.
00018 // 
00019 // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00020 // http://xorp.net
00021 
00022 
00023 #ifndef __LIBXORP_TIMEVAL_HH__
00024 #define __LIBXORP_TIMEVAL_HH__
00025 
00026 #include "xorp.h"
00027 #include "random.h"
00028 
00029 #ifdef HAVE_SYS_TIME_H
00030 #include <sys/time.h>
00031 #endif
00032 
00033 #include <math.h>
00034 
00035 
00036 // TODO:  Move this out-of-line (let compiler make the decision)
00037 // TODO:  Allow setting values, and remove return-by-value where possible.
00038 
00045 class TimeVal {
00046 public:
00047     static const int32_t ONE_MILLION = 1000000;
00048     static const int32_t ONE_THOUSAND = 1000;
00049 #ifdef HOST_OS_WINDOWS
00050     /*
00051      * The difference between the beginning of the Windows epoch
00052      * (1601-01-01-00-00) and the UNIX epoch (1970-01-01-00-00)
00053      * is 134,774 days on the Julian calendar. Compute this
00054      * difference in seconds and use it as a constant.
00055      * XXX: This does not take account of leap seconds.
00056      */
00057     static const int64_t UNIX_WIN32_EPOCH_DIFF = (134774LL * 24LL * 60LL * 60LL);
00058     static const int32_t UNITS_100NS_PER_1US = 10;
00059 #endif
00060 
00061 public:
00065     TimeVal() : _sec(0), _usec(0) {}
00066 
00073     TimeVal(int32_t sec, int32_t usec) : _sec(sec), _usec(usec) {}
00074 
00075 #ifndef HOST_OS_WINDOWS
00076 
00083     explicit TimeVal(const timeval& timeval)
00084     : _sec(timeval.tv_sec), _usec(timeval.tv_usec) {}
00085 
00086 #ifdef HAVE_STRUCT_TIMESPEC
00087 
00093     explicit TimeVal(const timespec& timespec)
00094     : _sec(timespec.tv_sec), _usec(timespec.tv_nsec / 1000) {}
00095 #endif
00096 
00097 #else /* HOST_OS_WINDOWS */
00098 
00104     explicit TimeVal(const FILETIME& ft) { copy_in(ft); }
00105 
00106 #endif /* !HOST_OS_WINDOWS */
00107 
00113     explicit TimeVal(const double& d);
00114 
00120     int32_t sec() const     { return _sec; }
00121 
00127     int32_t usec() const    { return _usec; }
00128 
00132     string str() const;
00133 
00139     string pretty_print() const;
00140 
00144     static TimeVal ZERO();
00145 
00149     static TimeVal MAXIMUM();
00150 
00154     static TimeVal MINIMUM();
00155 
00162     size_t copy_in(const timeval& timeval);
00163 
00170     size_t copy_out(timeval& timeval) const;
00171 
00172 #ifdef HAVE_STRUCT_TIMESPEC
00173 
00179     size_t copy_in(const timespec& timespec);
00180 
00187     size_t copy_out(timespec& timespec) const;
00188 #endif
00189 
00198     int64_t to_ms() const;
00199 
00200     void set_ms(int64_t ms);
00201 
00202 #ifdef HOST_OS_WINDOWS
00203 
00209     size_t copy_in(const FILETIME& filetime);
00210 
00217     size_t copy_out(FILETIME& filetime) const;
00218 
00219 #endif /* HOST_OS_WINDOWS */
00220 
00226     double get_double() const { return (_sec * 1.0 + _usec * 1.0e-6); }
00227 
00231     TimeVal& operator=(const TimeVal& other);
00232 
00240     bool operator==(const TimeVal& other) const;
00241 
00249     bool operator<(const TimeVal& other) const;
00250 
00257     const TimeVal& operator+=(const TimeVal& delta);
00258 
00266     TimeVal operator+(const TimeVal& other) const;
00267 
00274     const TimeVal& operator-=(const TimeVal& delta);
00275 
00283     TimeVal operator-(const TimeVal& other) const;
00284 
00293     TimeVal operator*(int n) const;
00294 
00303     TimeVal operator*(unsigned int n) const;
00304 
00313     TimeVal operator*(const double& d) const;
00314 
00323     TimeVal operator/(int n) const;
00324 
00333     TimeVal operator/(unsigned int n) const;
00334 
00343     TimeVal operator/(const double& d) const;
00344 
00350     bool is_zero() const    { return ((_sec == 0) && (_usec == 0)); }
00351 
00352 private:
00353     TimeVal(int i);     // Not implemented
00354 
00355     int32_t _sec;       // The number of seconds
00356     int32_t _usec;      // The number of microseconds
00357 };
00358 
00359 inline
00360 TimeVal::TimeVal(const double& d)
00361     : _sec((int32_t)d),
00362       _usec((int32_t)((d - ((double)_sec)) * ONE_MILLION + 0.5e-6))
00363 {
00364     //
00365     // Adjust
00366     //
00367     if (_usec >= ONE_MILLION) {
00368     _sec += _usec / ONE_MILLION;
00369     _usec %= ONE_MILLION;
00370     }
00371 }
00372 
00373 inline size_t
00374 TimeVal::copy_in(const timeval& timeval)
00375 {
00376     _sec = timeval.tv_sec;
00377     _usec = timeval.tv_usec;
00378     return (sizeof(_sec) + sizeof(_usec));
00379 }
00380 
00381 inline size_t
00382 TimeVal::copy_out(timeval& timeval) const
00383 {
00384     timeval.tv_sec = _sec;
00385     timeval.tv_usec = _usec;
00386     return (sizeof(_sec) + sizeof(_usec));
00387 }
00388 
00389 #ifdef HAVE_STRUCT_TIMESPEC
00390 
00391 inline size_t
00392 TimeVal::copy_in(const timespec& timespec)
00393 {
00394     _sec = timespec.tv_sec;
00395     _usec = timespec.tv_nsec / 1000;
00396     return (sizeof(_sec) + sizeof(_usec));
00397 }
00398 
00399 inline size_t
00400 TimeVal::copy_out(timespec& timespec) const
00401 {
00402     timespec.tv_sec = _sec;
00403     timespec.tv_nsec = _usec * 1000;
00404     return (sizeof(_sec) + sizeof(_usec));
00405 }
00406 
00407 #endif
00408 
00409 #ifdef HOST_OS_WINDOWS
00410 
00411 /*
00412  * Convert Windows time to a BSD struct timeval using 64-bit integer
00413  * arithmetic, by the following steps:
00414  * 1. Scale Windows' 100ns resolution to BSD's 1us resolution.
00415  * 2. Subtract the difference since the beginning of their respective epochs.
00416  * 3. Extract the appropriate fractional parts from the 64-bit
00417  *    integer used to represent Windows time.
00418  * Both UNIX and NT time systems correspond to UTC, therefore leap second
00419  * correction is NTP's problem.
00420  */
00421 inline size_t
00422 TimeVal::copy_in(const FILETIME& filetime)
00423 {
00424     ULARGE_INTEGER ui;
00425 
00426     ui.LowPart = filetime.dwLowDateTime;
00427     ui.HighPart = filetime.dwHighDateTime;
00428     ui.QuadPart /= UNITS_100NS_PER_1US;
00429     ui.QuadPart -= UNIX_WIN32_EPOCH_DIFF * ONE_MILLION;
00430     _usec = ui.QuadPart % ONE_MILLION;
00431     _sec = ui.QuadPart / ONE_MILLION;
00432     return (sizeof(filetime.dwLowDateTime) + sizeof(filetime.dwHighDateTime));
00433 }
00434 
00435 inline size_t
00436 TimeVal::copy_out(FILETIME& filetime) const
00437 {
00438     ULARGE_INTEGER ui;
00439 
00440     ui.QuadPart = _sec + UNIX_WIN32_EPOCH_DIFF;
00441     ui.QuadPart *= ONE_MILLION;
00442     ui.QuadPart += _usec;
00443     ui.QuadPart *= UNITS_100NS_PER_1US;
00444     filetime.dwLowDateTime = ui.LowPart;
00445     filetime.dwHighDateTime = ui.HighPart;
00446     return (sizeof(filetime.dwLowDateTime) + sizeof(filetime.dwHighDateTime));
00447 }
00448 
00449 #endif /* HOST_OS_WINDOWS */
00450 
00451 inline TimeVal&
00452 TimeVal::operator=(const TimeVal& other)
00453 {
00454     _sec = other.sec();
00455     _usec = other.usec();
00456     return *this;
00457 }
00458 
00459 inline bool
00460 TimeVal::operator==(const TimeVal& other) const
00461 {
00462     return (_sec == other.sec()) && (_usec == other.usec());
00463 }
00464 
00465 inline bool
00466 TimeVal::operator<(const TimeVal& other) const
00467 {
00468     return (_sec == other.sec()) ? _usec < other.usec() : _sec < other.sec();
00469 }
00470 
00471 inline const TimeVal&
00472 TimeVal::operator+=(const TimeVal& delta)
00473 {
00474     _sec += delta.sec();
00475     _usec += delta.usec();
00476     if (_usec >= ONE_MILLION) {
00477     _sec++;
00478     _usec -= ONE_MILLION;
00479     }
00480     return (*this);
00481 }
00482 
00483 inline TimeVal
00484 TimeVal::operator+(const TimeVal& other) const
00485 {
00486     TimeVal tmp_tv(*this);
00487     return tmp_tv += other;
00488 }
00489 
00490 inline const TimeVal&
00491 TimeVal::operator-=(const TimeVal& delta)
00492 {
00493     _sec -= delta.sec();
00494     if (_usec < delta.usec()) {
00495     // Compensate
00496     _sec--;
00497     _usec += ONE_MILLION;
00498     }
00499     _usec -= delta.usec();
00500 
00501     return (*this);
00502 }
00503 
00504 inline TimeVal
00505 TimeVal::operator-(const TimeVal& other) const
00506 {
00507     TimeVal tmp_tv(*this);
00508     return tmp_tv -= other;
00509 }
00510 
00511 inline TimeVal
00512 TimeVal::operator*(int n) const
00513 {
00514     uint32_t tmp_sec, tmp_usec;
00515 
00516     tmp_usec = _usec * n;
00517     tmp_sec = _sec * n + tmp_usec / ONE_MILLION;
00518     tmp_usec %= ONE_MILLION;
00519     return TimeVal(tmp_sec, tmp_usec);
00520 }
00521 
00522 inline TimeVal
00523 TimeVal::operator*(unsigned int n) const
00524 {
00525     return (*this)*(static_cast<int>(n));
00526 }
00527 
00528 inline TimeVal
00529 TimeVal::operator*(const double& d) const
00530 {
00531     return TimeVal(get_double() * d);
00532 }
00533 
00534 inline TimeVal
00535 TimeVal::operator/(int n) const
00536 {
00537     return TimeVal(_sec / n, ((_sec % n) * ONE_MILLION + _usec) / n);
00538 }
00539 
00540 inline TimeVal
00541 TimeVal::operator/(unsigned int n) const
00542 {
00543     return (*this)/(static_cast<int>(n));
00544 }
00545 
00546 inline TimeVal
00547 TimeVal::operator/(const double& d) const
00548 {
00549     return TimeVal(get_double() / d);
00550 }
00551 
00552 inline TimeVal
00553 TimeVal::ZERO()
00554 {
00555     return TimeVal(0, 0);
00556 }
00557 
00558 inline TimeVal
00559 TimeVal::MAXIMUM()
00560 {
00561     return TimeVal(0x7fffffff, ONE_MILLION - 1);
00562 }
00563 
00564 inline TimeVal
00565 TimeVal::MINIMUM()
00566 {
00567     return TimeVal(- 0x7fffffff - 1, - (ONE_MILLION - 1));
00568 }
00569 
00573 inline TimeVal
00574 operator-(const TimeVal& v)
00575 {
00576     return TimeVal(-v.sec(), -v.usec());
00577 }
00578 
00582 inline TimeVal
00583 operator*(int n, const TimeVal& t)
00584 {
00585     return t * n;
00586 }
00587 
00591 inline TimeVal
00592 operator*(const double& d, const TimeVal& t)
00593 {
00594     return t * d;
00595 }
00596 
00604 inline TimeVal
00605 random_uniform(const TimeVal& lower, const TimeVal& upper)
00606 {
00607     double d = (upper - lower).get_double();
00608     d *= double(xorp_random()) / double(XORP_RANDOM_MAX);
00609     return lower + TimeVal(d);
00610 }
00611 
00618 inline TimeVal
00619 random_uniform(const TimeVal& upper)
00620 {
00621     double d = upper.get_double();
00622     d *= double(xorp_random()) / double(XORP_RANDOM_MAX);
00623     return TimeVal(d);
00624 }
00625 
00636 inline TimeVal
00637 random_uniform(const TimeVal& center, const double& factor)
00638 {
00639     TimeVal l = max(center - center * factor, TimeVal::ZERO());
00640     TimeVal u = center + center * factor;
00641     return random_uniform(l, u);
00642 }
00643 
00644 #endif // __LIBXORP_TIMEVAL_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations