IBR-DTNSuite  0.10
TimeMeasurement.cpp
Go to the documentation of this file.
1 /*
2  * TimeMeasurement.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
22 #include "ibrcommon/config.h"
24 #include <iostream>
25 #include <iomanip>
26 #include <stdio.h>
27 
28 #ifdef HAVE_FEATURES_H
29 #include <features.h>
30 #endif
31 
32 #ifdef HAVE_MACH_MACH_TIME_H
33 #include <mach/mach_time.h>
34 #include <mach/clock.h>
35 #include <mach/mach.h>
36 #endif
37 
38 namespace ibrcommon
39 {
41  {
42  start(); stop();
43  }
44 
46  {
47  }
48 
50  {
51  // set start time
52  gettime(&_start);
53  }
54 
56  {
57  // set stop time
58  gettime(&_end);
59  }
60 
62  {
63  struct timespec diff;
64  getTime(diff);
65 
66  // merge seconds and nanoseconds
67  double delay_us = ((double)diff.tv_sec * 1000.0) + ((double)diff.tv_nsec / 1000000.0);
68 
69  return delay_us;
70  }
71 
73  {
74  struct timespec diff;
75  getTime(diff);
76 
77  // merge seconds and nanoseconds
78  double delay_us = ((double)diff.tv_sec * 1000000.0) + ((double)diff.tv_nsec / 1000.0);
79 
80  return delay_us;
81  }
82 
84  {
85  return _end.tv_sec - _start.tv_sec;
86  }
87 
88  std::ostream& TimeMeasurement::format(std::ostream &stream, const double value)
89  {
90 #ifdef __UCLIBC__
91  char buf[32];
92  snprintf(buf, 32, "%4.2f", value);
93  stream << std::string(buf);
94 #else
95  stream << std::setiosflags(std::ios::fixed) << std::setprecision(2) << value;
96 #endif
97  return stream;
98  }
99 
100  std::ostream &operator<<(std::ostream &stream, const TimeMeasurement &measurement)
101  {
102  struct timespec diff;
103  measurement.getTime(diff);
104 
105  // convert nanoseconds to milliseconds
106  double delay_ms = (double)diff.tv_nsec / 1000000.0;
107 
108  if (diff.tv_sec < 1)
109  {
110  TimeMeasurement::format(stream, delay_ms); stream << " ms";
111  return stream;
112  }
113 
114  // convert time interval to seconds
115  double seconds = (double)diff.tv_sec + (delay_ms / 1000.0);
116 
117  if (diff.tv_sec >= 3600)
118  {
119  TimeMeasurement::format(stream, seconds / 3600.0); stream << " h";
120  }
121  else if (diff.tv_sec >= 60)
122  {
123  TimeMeasurement::format(stream, seconds / 60.0); stream << " m";
124  }
125  else
126  {
127  TimeMeasurement::format(stream, seconds); stream << " s";
128  }
129 
130  return stream;
131  }
132 
133  void TimeMeasurement::getTime(struct timespec &diff) const
134  {
135  if ((_end.tv_nsec - _start.tv_nsec) < 0)
136  {
137  diff.tv_sec = _end.tv_sec - _start.tv_sec - 1;
138  diff.tv_nsec = (1000000000 + _end.tv_nsec) - _start.tv_nsec;
139  }
140  else
141  {
142  diff.tv_sec = _end.tv_sec - _start.tv_sec;
143  diff.tv_nsec = _end.tv_nsec - _start.tv_nsec;
144  }
145  }
146 
147  void TimeMeasurement::gettime(struct timespec *ts)
148  {
149 #ifdef HAVE_MACH_MACH_TIME_H // OS X does not have clock_gettime, use clock_get_time
150  clock_serv_t cclock;
151  mach_timespec_t mts;
152  host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &cclock);
153  clock_get_time(cclock, &mts);
154  mach_port_deallocate(mach_task_self(), cclock);
155  ts->tv_sec = mts.tv_sec;
156  ts->tv_nsec = mts.tv_nsec;
157 #else
158  ::clock_gettime(CLOCK_MONOTONIC, ts);
159 #endif
160  }
161 }