IBR-DTNSuite  0.8
ibrcommon/ibrcommon/TimeMeasurement.cpp
Go to the documentation of this file.
00001 /*
00002  * TimeMeasurement.cpp
00003  *
00004  *  Created on: 20.01.2010
00005  *      Author: morgenro
00006  */
00007 
00008 #include "ibrcommon/config.h"
00009 #include "ibrcommon/TimeMeasurement.h"
00010 #include <iostream>
00011 #include <iomanip>
00012 #include <stdio.h>
00013 
00014 #ifdef HAVE_FEATURES_H
00015 #include <features.h>
00016 #endif
00017 
00018 #ifdef HAVE_MACH_MACH_TIME_H
00019 #include <mach/mach_time.h>
00020 #endif
00021 
00022 namespace ibrcommon
00023 {
00024         TimeMeasurement::TimeMeasurement()
00025         {
00026                 start(); stop();
00027         }
00028 
00029         TimeMeasurement::~TimeMeasurement()
00030         {
00031         }
00032 
00033         void TimeMeasurement::start()
00034         {
00035 #ifdef HAVE_MACH_MACH_TIME_H
00036                 _uint64_start = mach_absolute_time();
00037 #else
00038                 // set sending time
00039                 clock_gettime(CLOCK_MONOTONIC, &_start);
00040 
00041 #endif
00042         }
00043 
00044         void TimeMeasurement::stop()
00045         {
00046 #ifdef HAVE_MACH_MACH_TIME_H
00047                 _uint64_end = mach_absolute_time();
00048 #else
00049                 // set receiving time
00050                 clock_gettime(CLOCK_MONOTONIC, &_end);
00051 #endif
00052         }
00053 
00054         float TimeMeasurement::getMilliseconds() const
00055         {
00056                 // calc difference
00057                 u_int64_t timeElapsed = getNanoseconds();
00058 
00059                 // make it readable
00060                 float delay_ms = (float)timeElapsed / 1000000;
00061 
00062                 return delay_ms;
00063         }
00064 
00065         u_int64_t TimeMeasurement::getNanoseconds() const
00066         {
00067                 // calc difference
00068 #ifdef HAVE_MACH_MACH_TIME_H
00069                 int64_t val = TimeMeasurement::timespecDiff(_uint64_end, _uint64_start);
00070 #else
00071                 int64_t val = TimeMeasurement::timespecDiff(&_end, &_start);
00072 #endif
00073 
00074                 if (val < 0) return 0;
00075                 return val;
00076         }
00077 
00078         float TimeMeasurement::getMicroseconds() const
00079         {
00080                 // calc difference
00081                 u_int64_t timeElapsed = getNanoseconds();
00082 
00083                 // make it readable
00084                 float delay_m = (float)timeElapsed / 1000;
00085 
00086                 return delay_m;
00087         }
00088 
00089         float TimeMeasurement::getSeconds() const
00090         {
00091                 return getMilliseconds() / 1000;
00092         }
00093 
00094         std::ostream& TimeMeasurement::format(std::ostream &stream, const float value)
00095         {
00096 #ifdef __UCLIBC__
00097                 char buf[32];
00098                 snprintf(buf, 32, "%4.2f", value);
00099                 stream << std::string(buf);
00100 #else
00101                 stream << std::setiosflags(std::ios::fixed) << std::setprecision(2) << value;
00102 #endif
00103                 return stream;
00104         }
00105 
00106         std::ostream &operator<<(std::ostream &stream, const TimeMeasurement &measurement)
00107         {
00108                 // calc difference
00109 #ifdef HAVE_MACH_MACH_TIME_H
00110                 u_int64_t timeElapsed = TimeMeasurement::timespecDiff(measurement._uint64_end, measurement._uint64_start);
00111 #else
00112                 u_int64_t timeElapsed = TimeMeasurement::timespecDiff(&(measurement._end), &(measurement._start));
00113 #endif
00114 
00115                 // make it readable
00116                 float delay_ms = (float)timeElapsed / 1000000;
00117                 float delay_sec = delay_ms / 1000;
00118                 float delay_min = delay_sec / 60;
00119                 float delay_h = delay_min / 60;
00120 
00121                 if (delay_h > 1)
00122                 {
00123                         TimeMeasurement::format(stream, delay_h); stream << " h";
00124                 }
00125                 else if (delay_min > 1)
00126                 {
00127                         TimeMeasurement::format(stream, delay_min); stream << " m";
00128                 }
00129                 else if (delay_sec > 1)
00130                 {
00131                         TimeMeasurement::format(stream, delay_sec); stream << " s";
00132                 }
00133                 else
00134                 {
00135                         TimeMeasurement::format(stream, delay_ms); stream << " ms";
00136                 }
00137 
00138                 return stream;
00139         }
00140 
00141         int64_t TimeMeasurement::timespecDiff(const uint64_t &timeA, const uint64_t &timeB)
00142         {
00143                 int64_t duration = timeA - timeB;
00144 
00145 #ifdef HAVE_MACH_MACH_TIME_H
00146                 mach_timebase_info_data_t info;
00147                 mach_timebase_info(&info);
00148 
00149                 /* Convert to nanoseconds */
00150                 duration *= info.numer;
00151                 duration /= info.denom;
00152 #endif
00153                 return duration;
00154         }
00155 
00156         int64_t TimeMeasurement::timespecDiff(const struct timespec *timeA_p, const struct timespec *timeB_p)
00157         {
00158                 //Casting to 64Bit, otherwise it caps out at ~ 5 secs for 32bit machines
00159                 return ( ( (int64_t)(timeA_p->tv_sec) * 1e9 + (int64_t)(timeA_p->tv_nsec)) -  ( (int64_t)(timeB_p->tv_sec) * 1e9 + (int64_t)(timeB_p->tv_nsec)) );
00160         }
00161 }