IBR-DTNSuite  0.12
MonotonicClock.cpp
Go to the documentation of this file.
1 /*
2  * MonotonicClock.cpp
3  *
4  * Created on: 10.09.2013
5  * Author: morgenro
6  */
7 
8 #include "ibrcommon/config.h"
10 #include <time.h>
11 
12 #ifdef HAVE_FEATURES_H
13 #include <features.h>
14 #endif
15 
16 #ifdef HAVE_MACH_MACH_TIME_H
17 #include <mach/mach_time.h>
18 #include <mach/clock.h>
19 #include <mach/mach.h>
20 #endif
21 
22 namespace ibrcommon {
23 
25  {
26  gettime(_start);
27  }
28 
30  {
31  }
32 
33  void MonotonicClock::get(struct timeval &tv) const
34  {
35  struct timespec ts;
36  get(ts);
37 
38  tv.tv_sec = ts.tv_sec;
39  tv.tv_usec = ts.tv_nsec / 1000;
40  }
41 
42  void MonotonicClock::get(struct timespec &ts) const
43  {
44  struct timespec now;
46  MonotonicClock::diff(_start, now, ts);
47  }
48 
50  {
51  struct timespec t;
52  get(t);
53  return t.tv_sec;
54  }
55 
56 #ifdef __WIN32__
57  LARGE_INTEGER MonotonicClock::getFILETIMEoffset()
58  {
59  SYSTEMTIME s;
60  FILETIME f;
61  LARGE_INTEGER t;
62 
63  s.wYear = 1970;
64  s.wMonth = 1;
65  s.wDay = 1;
66  s.wHour = 0;
67  s.wMinute = 0;
68  s.wSecond = 0;
69  s.wMilliseconds = 0;
70  SystemTimeToFileTime(&s, &f);
71  t.QuadPart = f.dwHighDateTime;
72  t.QuadPart <<= 32;
73  t.QuadPart |= f.dwLowDateTime;
74  return (t);
75  }
76 #endif
77 
78  void MonotonicClock::gettime(struct timeval &tv)
79  {
80  struct timespec ts;
81  gettime(ts);
82 
83  tv.tv_sec = ts.tv_sec;
84  tv.tv_usec = ts.tv_nsec / 1000;
85  }
86 
87  void MonotonicClock::gettime(struct timespec &ts)
88  {
89 #ifdef __WIN32__
90  LARGE_INTEGER t;
91  FILETIME f;
92  double microseconds;
93  static LARGE_INTEGER offset;
94  static double frequencyToMicroseconds;
95  static int initialized = 0;
96  static BOOL usePerformanceCounter = 0;
97 
98  if (!initialized) {
99  LARGE_INTEGER performanceFrequency;
100  initialized = 1;
101  usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency);
102  if (usePerformanceCounter) {
103  QueryPerformanceCounter(&offset);
104  frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.;
105  } else {
106  offset = getFILETIMEoffset();
107  frequencyToMicroseconds = 10.;
108  }
109  }
110  if (usePerformanceCounter) QueryPerformanceCounter(&t);
111  else {
112  GetSystemTimeAsFileTime(&f);
113  t.QuadPart = f.dwHighDateTime;
114  t.QuadPart <<= 32;
115  t.QuadPart |= f.dwLowDateTime;
116  }
117 
118  t.QuadPart -= offset.QuadPart;
119  microseconds = (double)t.QuadPart / frequencyToMicroseconds;
120  t.QuadPart = microseconds;
121  ts.tv_sec = t.QuadPart / 1000000;
122  ts.tv_nsec = (t.QuadPart % 1000000) * 1000;
123 #elif HAVE_MACH_MACH_TIME_H // OS X does not have clock_gettime, use clock_get_time
124  clock_serv_t cclock;
125  mach_timespec_t mts;
126  host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &cclock);
127  clock_get_time(cclock, &mts);
128  mach_port_deallocate(mach_task_self(), cclock);
129  ts.tv_sec = mts.tv_sec;
130  ts.tv_nsec = mts.tv_nsec;
131 #else
132  ::clock_gettime(CLOCK_MONOTONIC, &ts);
133 #endif
134  }
135 
136  void MonotonicClock::diff(const struct timespec &start, const struct timespec &end, struct timespec &diff)
137  {
138  if ((end.tv_nsec - start.tv_nsec) < 0)
139  {
140  diff.tv_sec = end.tv_sec - start.tv_sec - 1;
141  diff.tv_nsec = (1000000000 + end.tv_nsec) - start.tv_nsec;
142  }
143  else
144  {
145  diff.tv_sec = end.tv_sec - start.tv_sec;
146  diff.tv_nsec = end.tv_nsec - start.tv_nsec;
147  }
148  }
149 
150 } /* namespace ctrl */