Scarab
Project 8 C++ Utility Library
time.cc
Go to the documentation of this file.
1 /*
2  * time.cc
3  *
4  * Created on: Oct 29, 2013
5  * Author: nsoblath
6  */
7 
8 
9 #define SCARAB_API_EXPORTS
10 
11 #include "time.hh"
12 
13 namespace scarab
14 {
15 
16 // Combined date & time, according to the ISO 8601 standard: e.g. 2015-01-31T22:35:58Z
17 SCARAB_API char date_time_format[] = "%Y-%m-%dT%H:%M:%SZ";
18 
19 #ifdef __MACH__
20 double thorax_timebase = 0.0;
21 time_nsec_type thorax_timestart = 0;
22 #endif
23 
24 #ifdef _WIN32
25 #define CLOCK_MONOTONIC 1
26 #define CLOCK_PROCESS_CPUTIME_ID 2
27 #endif
28 
29 SCARAB_API int get_time_monotonic( struct timespec* time )
30 {
31 #ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
32  if (! thorax_timestart)
33  {
34  mach_timebase_info_data_t tb = { .numer = 0, .denom = 1 };
35  mach_timebase_info(&tb);
36  thorax_timebase = tb.numer;
37  thorax_timebase /= tb.denom;
38  thorax_timestart = mach_absolute_time();
39  }
40  double diff = (mach_absolute_time() - thorax_timestart) * thorax_timebase;
41  time->tv_sec = diff * MACNANO;
42  time->tv_nsec = diff - (time->tv_sec * MACGIGA);
43  return 0;
44 #else
45  return clock_gettime( CLOCK_MONOTONIC, time );
46 #endif
47 }
48 
49 SCARAB_API int get_time_current( struct timespec* time )
50 {
51 #ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
52  if (! thorax_timestart)
53  {
54  mach_timebase_info_data_t tb = { .numer = 0, .denom = 1 };
55  mach_timebase_info(&tb);
56  thorax_timebase = tb.numer;
57  thorax_timebase /= tb.denom;
58  thorax_timestart = mach_absolute_time();
59  }
60  double diff = (mach_absolute_time() - thorax_timestart) * thorax_timebase;
61  time->tv_sec = diff * MACNANO;
62  time->tv_nsec = diff - (time->tv_sec * MACGIGA);
63  return 0;
64 #else
65  return clock_gettime(CLOCK_PROCESS_CPUTIME_ID, time);
66 #endif
67 
68 }
69 
70 SCARAB_API time_nsec_type time_to_nsec( struct timespec time )
71 {
72  return (long long int)time.tv_sec * (long long int)NSEC_PER_SEC + (long long int)time.tv_nsec;
73 }
74 
75 SCARAB_API double time_to_sec( struct timespec time )
76 {
77  return (double)time.tv_sec + (double)time.tv_nsec / (double)NSEC_PER_SEC;
78 }
79 
80 SCARAB_API void time_diff( struct timespec start, struct timespec end, struct timespec* diff )
81 {
82  if ((end.tv_nsec - start.tv_nsec < 0))
83  {
84  diff->tv_sec = end.tv_sec - start.tv_sec - 1;
85  diff->tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
86  }
87  else
88  {
89  diff->tv_sec = end.tv_sec - start.tv_sec;
90  diff->tv_nsec = end.tv_nsec - start.tv_nsec;
91  }
92  return;
93 }
94 
95 SCARAB_API size_t get_time_absolute_str( char* ptr )
96 {
97  time_t raw_time;
98  struct tm* processed_time;
99 
100  time(&raw_time);
101  processed_time = gmtime(&raw_time);
102  return strftime(ptr, 512, date_time_format, processed_time);
103 }
104 
106 {
107  char t_string_time[ 512 ];
108  get_time_absolute_str( t_string_time );
109  return std::string( t_string_time );
110 }
111 
112 
113 #ifdef _WIN32
114 SCARAB_API LARGE_INTEGER getFILETIMEoffset()
115 {
116  SYSTEMTIME s;
117  FILETIME f;
118  LARGE_INTEGER t;
119 
120  s.wYear = 1970;
121  s.wMonth = 1;
122  s.wDay = 1;
123  s.wHour = 0;
124  s.wMinute = 0;
125  s.wSecond = 0;
126  s.wMilliseconds = 0;
127  SystemTimeToFileTime(&s, &f);
128  t.QuadPart = f.dwHighDateTime;
129  t.QuadPart <<= 32;
130  t.QuadPart |= f.dwLowDateTime;
131  return (t);
132 }
133 
134 SCARAB_API int clock_gettime( int X, struct timespec *tv )
135 {
136  LARGE_INTEGER t;
137  FILETIME f;
138  double microseconds;
139  static LARGE_INTEGER offset;
140  static double frequencyToMicroseconds;
141  static int initialized = 0;
142  static BOOL usePerformanceCounter = 0;
143 
144  if (!initialized)
145  {
146  LARGE_INTEGER performanceFrequency;
147  initialized = 1;
148  usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency);
149  if (usePerformanceCounter)
150  {
151  QueryPerformanceCounter(&offset);
152  frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.;
153  }
154  else
155  {
156  offset = getFILETIMEoffset();
157  frequencyToMicroseconds = 10.;
158  }
159  }
160  if (usePerformanceCounter) QueryPerformanceCounter(&t);
161  else
162  {
163  GetSystemTimeAsFileTime(&f);
164  t.QuadPart = f.dwHighDateTime;
165  t.QuadPart <<= 32;
166  t.QuadPart |= f.dwLowDateTime;
167  }
168 
169  t.QuadPart -= offset.QuadPart;
170  microseconds = (double)t.QuadPart / frequencyToMicroseconds;
171  t.QuadPart = microseconds;
172  tv->tv_sec = t.QuadPart * SEC_PER_NSEC;
173  tv->tv_nsec = t.QuadPart % NSEC_PER_SEC;
174  return (0);
175 }
176 #endif
177 
178 } /* namespace scarab */
SCARAB_API double time_to_sec(struct timespec time)
Definition: time.cc:75
SCARAB_API time_nsec_type time_to_nsec(struct timespec time)
Definition: time.cc:70
SCARAB_API size_t get_time_absolute_str(char *ptr)
Definition: time.cc:95
#define SCARAB_API
Definition: scarab_api.hh:24
uint64_t time_nsec_type
Definition: time.hh:22
SCARAB_API int get_time_monotonic(struct timespec *time)
Definition: time.cc:29
#define SEC_PER_NSEC
Definition: time.hh:30
SCARAB_API int get_time_current(struct timespec *time)
Definition: time.cc:49
SCARAB_API void time_diff(struct timespec start, struct timespec end, struct timespec *diff)
Definition: time.cc:80
SCARAB_API char date_time_format[]
Definition: time.cc:17
SCARAB_API std::string get_absolute_time_string()
Definition: time.cc:105
#define NSEC_PER_SEC
Definition: time.hh:26