stime.cpp

00001 /*<std-header orig-src='shore'>
00002 
00003  $Id: stime.cpp,v 1.39 2010/05/26 01:20:22 nhall Exp $
00004 
00005 SHORE -- Scalable Heterogeneous Object REpository
00006 
00007 Copyright (c) 1994-99 Computer Sciences Department, University of
00008                       Wisconsin -- Madison
00009 All Rights Reserved.
00010 
00011 Permission to use, copy, modify and distribute this software and its
00012 documentation is hereby granted, provided that both the copyright
00013 notice and this permission notice appear in all copies of the
00014 software, derivative works or modified versions, and any portions
00015 thereof, and that both notices appear in supporting documentation.
00016 
00017 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY
00018 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS
00019 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND
00020 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
00021 
00022 This software was developed with support by the Advanced Research
00023 Project Agency, ARPA order number 018 (formerly 8230), monitored by
00024 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518.
00025 Further funding for this work was provided by DARPA through
00026 Rome Research Laboratory Contract No. F30602-97-2-0247.
00027 
00028 */
00029 
00030 #include "w_defines.h"
00031 
00032 /*  -- do not edit anything above this line --   </std-header>*/
00033 
00034 /**\cond skip */
00035 #include <ctime>
00036 #include <cstring>
00037 #include <w_base.h>
00038 #include <stime.h>
00039 #include <w_stream.h>
00040 #include <climits>
00041 
00042 /*
00043    All this magic is to allow either timevals or timespecs
00044    to be used without code change.  It's disgusting, but it
00045    avoid templates.  Templates are evil.
00046 
00047    st_tod    == time of day part of the time
00048    st_hires    == "higher resolution" part of the time
00049    HR_SECOND    == high-resolution units in a second
00050    TOD_MAX    == low-resolution (seconds) maximum value
00051  */  
00052 
00053 #define    NS_SECOND    1000000000    /* nanoseconds in a second */
00054 #define    US_SECOND    1000000    /* microseconds in a second */
00055 #define    MS_SECOND    1000    /* millisecs in a second */
00056 
00057 #ifdef USE_POSIX_TIME
00058 typedef    struct timespec _stime_t;
00059 #define    st_tod        tv_sec
00060 #define    st_hires    tv_nsec
00061 #define    HR_SECOND    NS_SECOND
00062 #else
00063 typedef struct timeval    _stime_t;
00064 #define    st_tod        tv_sec
00065 #define    st_hires    tv_usec
00066 #define    HR_SECOND    US_SECOND
00067 #endif
00068 
00069 #ifdef Alpha
00070 #define    TOD_MAX        INT_MAX
00071 #else
00072 #define    TOD_MAX        LONG_MAX
00073 #endif
00074 #define    HR_MAX        (HR_SECOND-1)
00075 
00076 
00077 
00078 
00079 /*
00080    XXX problems
00081 
00082    Rounding policy is currently ill-defined.  I need to choose one,
00083    and make sure the various input and output (to/from other type)
00084    operators implement it uniformly.  XXX This really needs to be
00085    fixed.
00086  */
00087 
00088 /* Internal constructor, exposes implementation */
00089 stime_t::stime_t(time_t tod, long hires)
00090 {
00091     _time.st_tod = tod;
00092     _time.st_hires = hires;
00093 
00094     normalize();
00095 }
00096 
00097 
00098 stime_t::stime_t(int secs)
00099 {
00100     _time.st_tod = secs;
00101     _time.st_hires = 0;
00102 
00103     /* the conversion automagically normalizes */
00104 }
00105 
00106 stime_t::stime_t(long secs)
00107 {
00108     _time.st_tod = secs;
00109     _time.st_hires = 0;
00110 
00111     /* the conversion automagically normalizes */
00112 }
00113 
00114 
00115 stime_t::stime_t(double secs)
00116 {
00117     _time.st_tod = (long) secs;
00118     _time.st_hires = (long) ((secs - _time.st_tod) * HR_SECOND);
00119 
00120     /* the conversion automagically normalizes */
00121 }
00122 
00123 
00124 #ifdef USE_POSIX_TIME
00125 stime_t::stime_t(const struct timespec &tv)
00126 {
00127     _time.st_tod = tv.tv_sec;
00128     _time.st_hires = tv.tv_nsec * (HR_SECOND / NS_SECOND);
00129 
00130     normalize();
00131 }
00132 #endif
00133 
00134 stime_t::stime_t(const struct timeval &tv)
00135 {
00136     _time.st_tod = tv.tv_sec;
00137     _time.st_hires = tv.tv_usec * (HR_SECOND / US_SECOND);
00138 
00139     normalize();
00140 }
00141 
00142 
00143 bool    stime_t::operator==(const stime_t &r) const
00144 {
00145     return _time.st_tod == r._time.st_tod &&
00146         _time.st_hires == r._time.st_hires;
00147 }
00148 
00149 
00150 bool    stime_t::operator<(const stime_t &r) const
00151 {
00152     if (_time.st_tod == r._time.st_tod)
00153         return _time.st_hires < r._time.st_hires;
00154     return _time.st_tod < r._time.st_tod;
00155 }
00156 
00157 
00158 bool    stime_t::operator<=(const stime_t &r) const
00159 {
00160     return *this == r  ||  *this < r;
00161 }
00162 
00163 
00164 static inline int sign(const int i)
00165 {
00166     return i > 0 ? 1 : i < 0 ? -1 : 0;
00167     
00168 }
00169 
00170 /* Put a stime into normal form, where the HIRES part
00171    will contain less than a TODs worth of HIRES time.
00172    Also, the signs of the TOD and HIRES parts should
00173    agree (unless TOD==0) */
00174 
00175 void stime_t::signs()
00176 {
00177     if (_time.st_tod  &&  _time.st_hires
00178         && sign(_time.st_tod) != sign(_time.st_hires)) {
00179 
00180         if (sign(_time.st_tod) == 1) {
00181             _time.st_tod--;
00182             _time.st_hires += HR_SECOND;
00183         }
00184         else {
00185             _time.st_tod++;
00186             _time.st_hires -= HR_SECOND;
00187         }
00188     }
00189 }
00190 
00191 /* off-by one */
00192 void stime_t::_normalize()
00193 {
00194     if (abs(_time.st_hires) >= HR_SECOND) {
00195         _time.st_tod += sign(_time.st_hires);
00196         _time.st_hires -= sign(_time.st_hires) * HR_SECOND;
00197     }
00198     signs();
00199 }
00200    
00201 
00202 /* something that could be completely wacked out */
00203 void stime_t::normalize()
00204 {
00205     int    factor;
00206 
00207     factor = _time.st_hires / HR_SECOND;
00208     if (factor) {
00209         _time.st_tod += factor;
00210         _time.st_hires -= HR_SECOND * factor;
00211     }
00212 
00213     signs();
00214 }
00215 
00216 
00217 stime_t    stime_t::operator-() const
00218 {
00219     stime_t    result;
00220 
00221     result._time.st_tod = -_time.st_tod;
00222     result._time.st_hires = -_time.st_hires;
00223 
00224     return result;
00225 }
00226 
00227 
00228 stime_t    stime_t::operator+(const stime_t &r) const
00229 {
00230     stime_t    result;
00231 
00232     result._time.st_tod  = _time.st_tod  + r._time.st_tod;
00233     result._time.st_hires = _time.st_hires + r._time.st_hires;
00234 
00235     result._normalize();
00236 
00237     return result;
00238 }
00239 
00240 
00241 stime_t    stime_t::operator-(const stime_t &r) const
00242 {
00243     return *this + -r;
00244 }
00245 
00246 
00247 stime_t stime_t::operator*(const int factor) const
00248 {
00249     stime_t    result;
00250 
00251     result._time.st_tod = _time.st_tod * factor;
00252     result._time.st_hires = _time.st_hires * factor;
00253     result.normalize();
00254 
00255     return result;
00256 }
00257 
00258 /* XXX
00259    Float scaling is stupid for the moment.  It doesn't need
00260    to use double arithmetic, instead it should use an
00261    intermediate normalization step which moves
00262    lost TOD units into the HIRES range.
00263 
00264    The double stuff at least makes it seem to work right.
00265  */  
00266 
00267 
00268 stime_t stime_t::operator/(const int factor) const
00269 {
00270     return *this / (double)factor;
00271 }
00272 
00273 
00274 stime_t    stime_t::operator*(const double factor) const
00275 {
00276     double d = *this;
00277     d *= factor;
00278     stime_t result(d); 
00279     result.normalize();
00280 
00281     return result;
00282 }
00283 
00284 
00285 stime_t    stime_t::operator/(const double factor) const
00286 {
00287     return *this * (1.0 / factor);
00288 }
00289 
00290 
00291 /* The operator X and operator X= can be written in terms of each other */
00292 stime_t &stime_t::operator+=(const stime_t &r)
00293 {
00294     _time.st_tod  += r._time.st_tod;
00295     _time.st_hires += r._time.st_hires;
00296 
00297     _normalize();
00298     
00299     return *this;
00300 }
00301 
00302 
00303 stime_t &stime_t::operator-=(const stime_t &r)
00304 {
00305     _time.st_tod  -= r._time.st_tod;
00306     _time.st_hires -= r._time.st_hires;
00307 
00308     _normalize();
00309     
00310     return *this;
00311 }
00312 
00313 
00314 stime_t::operator double() const
00315 {
00316     return _time.st_tod + _time.st_hires / (double) HR_SECOND;
00317 }
00318 
00319 
00320 stime_t::operator float() const
00321 {
00322     double res = (double) *this;
00323     return (float)res;
00324 //    return _time.st_tod + _time.st_hires / (float) HR_SECOND;
00325 }
00326 
00327 
00328 
00329 
00330 /* XXX do we want this conversion even if we are using timeval
00331    implementation on systems that have timespec? */
00332 #ifdef USE_POSIX_TIME
00333 stime_t::operator struct timespec() const
00334 {
00335     struct    timespec tv;
00336     tv.tv_sec = _time.st_tod;
00337     tv.tv_nsec = _time.st_hires;
00338     return tv;
00339 }
00340 #endif
00341 
00342 // for type conversion
00343 stime_t::operator struct timeval() const
00344 {
00345     struct    timeval tv;
00346     tv.tv_sec = _time.st_tod;
00347     /* This conversion may prevent overflow which may
00348        occurs with some values on some systems. */
00349     tv.tv_usec = _time.st_hires / (HR_SECOND / US_SECOND);
00350     return tv;
00351 }
00352 
00353 
00354 void    stime_t::gettime()
00355 {
00356     int    kr;
00357 #ifdef USE_POSIX_TIME
00358     kr = clock_gettime(CLOCK_REALTIME, &_time);
00359 #else
00360     kr = gettimeofday(&_time, 0);
00361 #endif
00362     if (kr == -1)
00363         W_FATAL(fcOS);
00364 }
00365 
00366 
00367 ostream    &stime_t::print(ostream &s) const
00368 {
00369     ctime(s);
00370 
00371     if (_time.st_hires) {
00372         stime_t    tod(_time.st_tod, 0);
00373 
00374         s << " and " << sinterval_t(*this - tod);
00375     }
00376 
00377     return s;
00378 }
00379 
00380 
00381 ostream &stime_t::ctime(ostream &s) const
00382 {
00383     /* the second field of the time structs should be a time_t */
00384     time_t    kludge = _time.st_tod;
00385     const   int buflen(26); 
00386     char    buf[buflen];    /* XXX well known magic number */
00387 
00388     /// See Makefile.generic for note about this
00389 #ifdef _POSIX_PTHREAD_SEMANTICS 
00390     char    *when = ctime_r(&kludge, buf);
00391 #elif defined(SOLARIS2)
00392     char    *when = ctime_r(&kludge, buf, buflen);
00393 #else
00394     char    *when = ctime_r(&kludge, buf);
00395 #endif
00396 
00397     /* chop the newline */
00398     char *nl = strchr(when, '\n');
00399     if (nl)
00400         *nl = '\0';
00401 
00402     return s << when;
00403 }
00404 
00405 
00406 static void factor_print(ostream &s, long what)
00407 {
00408     struct {
00409         const char    *label;
00410         int        factor;
00411     } factors[] = {
00412         {"%02d:", 60*60},
00413         {"%02d:", 60},
00414         {0, 0}
00415     }, *f = factors;
00416     long    mine;
00417     bool    printed = false;
00418     bool    negative = what < 0;
00419 
00420     if (negative) {
00421         s << '-';
00422         what = -what;
00423     }
00424 
00425     for (f = factors; f->label; f++) {
00426         mine = what / f->factor;
00427         what = what % f->factor;
00428         if (mine || printed) {
00429             W_FORM(s)(f->label, mine);
00430             printed = true;
00431         }
00432     }
00433 
00434     /* always print a seconds field */
00435     W_FORM(s)(printed ? "%02d" : "%d", what);
00436 }
00437 
00438 
00439 ostream    &sinterval_t::print(ostream &s) const
00440 {
00441     factor_print(s, _time.st_tod);
00442 
00443     if (_time.st_hires) {
00444 #ifdef USE_POSIX_TIME
00445         W_FORM(s)(".%09ld", _time.st_hires);
00446 #else
00447         W_FORM(s)(".%06ld", _time.st_hires);
00448 #endif
00449     }
00450 
00451     return s;
00452 }
00453 
00454 
00455 ostream &operator<<(ostream &s, const stime_t &t)
00456 {
00457     return t.print(s);
00458 }
00459 
00460 
00461 ostream &operator<<(ostream &s, const sinterval_t &t)
00462 {
00463     return t.print(s);
00464 }
00465 
00466 
00467 /* Input Conversion operators */
00468 
00469 static inline void from_linear(int sec, int xsec,
00470                 int linear_secs, _stime_t &_time)
00471 {
00472     _time.st_tod = sec + xsec / linear_secs;
00473     xsec = xsec % linear_secs;
00474     if (linear_secs > HR_SECOND)
00475         _time.st_hires = xsec / (linear_secs / HR_SECOND);
00476     else
00477         _time.st_hires = xsec * (HR_SECOND / linear_secs);
00478 }
00479 
00480 
00481 stime_t stime_t::sec(int sec)
00482 {
00483     stime_t    r;
00484 
00485     r._time.st_tod = sec;
00486     r._time.st_hires = 0;
00487 
00488     return r;
00489 }
00490 
00491 
00492 stime_t    stime_t::msec(int ms, int sec)
00493 {
00494     stime_t    r;
00495 
00496     from_linear(sec, ms, MS_SECOND, r._time);
00497     /* conversion normalizes */
00498 
00499     return r;
00500 }
00501 
00502     
00503 stime_t    stime_t::usec(int us, int sec)
00504 {
00505     stime_t    r;
00506 
00507     from_linear(sec, us, US_SECOND, r._time);
00508     /* conversion normalizes */
00509 
00510     return r;
00511 }
00512 
00513 
00514 stime_t    stime_t::nsec(int ns, int sec)
00515 {
00516     stime_t    r;
00517 
00518     from_linear(sec, ns, NS_SECOND, r._time);
00519     /* conversion normalizes */
00520 
00521     return r;
00522 }
00523 
00524 
00525 stime_t    stime_t::now()
00526 {
00527     stime_t    now;
00528     now.gettime();
00529 
00530     return now;
00531 }
00532 
00533 
00534 /* More conversion operators */
00535 /* For now, only the seconds conversion does rounding */ 
00536 
00537 /* roundup #seconds if hr_seconds >= this value */
00538 #define    HR_ROUNDUP    (HR_SECOND / 2)
00539 
00540 static    inline long to_linear(const _stime_t &_time, const int linear_secs)
00541 {
00542     long    result;
00543     int    factor;
00544 
00545     result = _time.st_tod * linear_secs;
00546 
00547     if (linear_secs > HR_SECOND) {
00548         factor = linear_secs / HR_SECOND;
00549         result += _time.st_hires * factor;
00550     }
00551     else {
00552         factor = HR_SECOND / linear_secs;
00553         result += _time.st_hires / factor;
00554     }
00555 
00556     return result;
00557 }
00558 
00559 
00560 long    stime_t::secs() const
00561 {
00562     long    result;
00563 
00564     result = _time.st_tod;
00565     if (_time.st_hires >= HR_ROUNDUP)
00566         result++;
00567 
00568     return result;
00569 }
00570 
00571 long    stime_t::msecs() const
00572 {
00573     return to_linear(_time, MS_SECOND);
00574 }
00575 
00576 long    stime_t::usecs() const
00577 {
00578     return to_linear(_time, US_SECOND);
00579 }
00580 
00581 long    stime_t::nsecs() const
00582 {
00583     return to_linear(_time, NS_SECOND);
00584 }
00585 
00586 /**\endcond skip */

Generated on Wed Jul 7 17:22:32 2010 for Shore Storage Manager by  doxygen 1.4.7