xtime.cpp
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13 ***************************************************************************/
14 #include "xtime.h"
15 #include <string.h>
16 #include <stdint.h>
17 #include "atomic.h"
18 
19 #ifdef USE_QTHREAD
20  #include <QThread>
21  #include <QDateTime>
22 #endif
23 #ifdef _MSC_VER
24  #include <windows.h>
25  #include <time.h>
26 #else
27  #include <sys/time.h>
28  #include <errno.h>
29 #endif
30 
31 void msecsleep(unsigned int ms) noexcept {
32 #ifdef USE_QTHREAD
33  XTime t0(XTime::now());
34  for(;;) {
35  unsigned int elapsed_ms = XTime::now().diff_msec(t0);
36  if(elapsed_ms >= ms)
37  break;
38  if(ms - elapsed_ms >= 30) {
39  QThread::msleep(ms - elapsed_ms);
40  }
41  else {
42  XTime t1(XTime::now());
43  QThread::yieldCurrentThread();
44  if(XTime::now().diff_msec(t1) > 1)
45  QThread::msleep(std::min(10u, ms - elapsed_ms)); //needs time slicing.
46  else {
47  pause4spin();
48  pause4spin();
49  pause4spin();
50  pause4spin();
51  }
52  }
53  }
54 #else //USE_QTHREAD
55  XTime t0(XTime::now());
56  XTime t1 = t0;
57  t0 += ms * 1e-3;
58  while(t1 < t0) {
59  struct timespec req;
60  req.tv_sec = (int)(t0 - t1);
61  req.tv_nsec = lrint((t0 - t1 - req.tv_sec) * 1e9);
62  if( !nanosleep(&req, NULL))
63  break;
64  t1 = XTime::now();
65  switch(errno) {
66  case EINTR:
67  continue;
68  default:
69  abort();
70  }
71  }
72 #endif //USE_QTHREAD
73 }
74 
75 timestamp_t timeStamp() noexcept {
76 #if defined __i386__ || defined __i486__ || defined __i586__ || defined __i686__ || defined __x86_64__
77  memoryBarrier();
78  uint64_t r;
79  #ifdef _MSC_VER
80  r = __rdtsc();
81  #else
82  asm volatile("rdtsc" : "=A" (r));
83  #endif
84  memoryBarrier();
85  return r;
86 #else
87  XTime time(XTime::now());
88  return (time.usec() + time.sec() * 1000000uL);
89 #endif
90 }
91 
92 static atomic<timestamp_t> s_time_stamp_cnt_per_ms = 0;
93 static atomic<timestamp_t> s_time_stamp_calc;
94 
95 DECLSPEC_KAME timestamp_t timeStampCountsPerMilliSec() noexcept {
96  if( !s_time_stamp_cnt_per_ms) {
97  for(;;) {
98  timestamp_t time_stamp_start = timeStamp();
99  s_time_stamp_calc = time_stamp_start;
100  XTime time_start(XTime::now());
101  timestamp_t time_stamp_start2 = timeStamp();
102  msecsleep(20);
103  timestamp_t dt = timeStamp() - time_stamp_start2;
104  unsigned int msec = XTime::now().diff_msec(time_start);
105  timestamp_t dt2 = timeStamp() - time_stamp_start;
106  s_time_stamp_cnt_per_ms = (dt+dt2)/2 / msec;
107 // fprintf(stderr, "Clocks per ms = %d\n", (int)s_time_stamp_cnt_per_ms);
108  if((double)dt2 / dt < 1.2)
109  break;
110  }
111  }
112  return s_time_stamp_cnt_per_ms;
113 }
114 
115 
116 XTime
117 XTime::now() noexcept {
118 #ifdef USE_QTHREAD
119  qint64 x = QDateTime::currentMSecsSinceEpoch();
120  return XTime(x / 1000LL, (x % 1000LL) * 1000l);
121 #else //USE_QTHREAD
122  timeval tv;
123  gettimeofday(&tv, NULL);
124  return XTime(tv.tv_sec, tv.tv_usec);
125 #endif //USE_QTHREAD
126 };
127 
128 XString
129 XTime::getTimeStr(bool subsecond) const {
130  if( *this) {
131  char str[100];
132 #ifdef _MSC_VER
133  __time32_t t32 = tv_sec;
134  __time64_t t64 = tv_sec;
135  if(sizeof(tv_sec) == 4)
136  _ctime32_s(str, sizeof(str) - 1, &t32);
137  else
138  _ctime64_s(str, sizeof(str) - 1, &t64);
139 #else
140  ctime_r( &tv_sec, str);
141 #endif
142  str[strlen(str) - 1] = '\0';
143  if(subsecond)
144  sprintf(str + strlen(str), " +%.3dms", (int)tv_usec/1000);
145  return str;
146  }
147  else {
148  return XString();
149  }
150 }
151 XString
152 XTime::getTimeFmtStr(const char *fmt, bool subsecond) const {
153  if( *this) {
154  struct tm time;
155 #ifdef _MSC_VER
156  __time32_t t32 = tv_sec;
157  __time64_t t64 = tv_sec;
158  if(sizeof(tv_sec) == 4)
159  _localtime32_s( &time, &t32);
160  else
161  _localtime64_s( &time, &t64);
162 #else
163  localtime_r( &tv_sec, &time);
164 #endif
165  char str[100];
166  strftime(str, 100, fmt, &time);
167  if(subsecond)
168  sprintf(str + strlen(str), " +%.3f", 1e-6 * tv_usec);
169  return str;
170  }
171  else {
172  return XString();
173  }
174 }
175 

Generated for KAME4 by  doxygen 1.8.3