Visual Servoing Platform  version 3.6.1 under development (2024-12-17)
vpTime.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Time management and measurement.
32  *
33 *****************************************************************************/
34 
40 #include <ctime>
41 
42 #include <visp3/core/vpTime.h>
43 
44 // https://devblogs.microsoft.com/cppblog/c14-stl-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1/
45 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11) && \
46  (defined(_MSC_VER) && _MSC_VER >= 1900 /* VS2015 */ || !defined(_MSC_VER))
47 #define USE_CXX11_CHRONO 1
48 #else
49 #define USE_CXX11_CHRONO 0
50 #endif
51 
52 // Unix depend version
53 
54 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
55 #include <sys/time.h>
56 #include <unistd.h>
57 #elif defined(_WIN32)
58 //#include <winbase.h>
59 #include <windows.h>
60 #endif
61 
62 BEGIN_VISP_NAMESPACE
63 #ifndef DOXYGEN_SHOULD_SKIP_THIS
64 namespace vpTime
65 {
66 #endif
67 
75 static const double minTimeForUsleepCall = 4;
76 
82 double getMinTimeForUsleepCall() { return minTimeForUsleepCall; }
83 
89 double measureTimeMicros()
90 {
91 #if USE_CXX11_CHRONO
92  std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
93  return std::chrono::duration<double, std::micro>(now.time_since_epoch()).count();
94 #else
95 #if defined(_WIN32)
96 #if !defined(WINRT)
97  LARGE_INTEGER time, frequency;
98  QueryPerformanceFrequency(&frequency);
99  if (frequency.QuadPart == 0) {
100  return (timeGetTime());
101  }
102  else {
103  QueryPerformanceCounter(&time);
104  return (double)(1000000.0 * time.QuadPart / frequency.QuadPart);
105  }
106 #else
107  throw(vpException(vpException::fatalError, "Cannot get time: not implemented on Universal Windows Platform"));
108 #endif
109 #elif !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
110  struct timeval tp;
111  gettimeofday(&tp, 0);
112  return (1000000.0 * tp.tv_sec + tp.tv_usec);
113 #endif
114 #endif
115 }
116 
123 double measureTimeMs()
124 {
125 #if USE_CXX11_CHRONO
126  std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
127  return std::chrono::duration<double, std::milli>(now.time_since_epoch()).count();
128 #else
129 #if defined(_WIN32)
130 #if !defined(WINRT)
131  LARGE_INTEGER time, frequency;
132  QueryPerformanceFrequency(&frequency);
133  if (frequency.QuadPart == 0) {
134  return (timeGetTime());
135  }
136  else {
137  QueryPerformanceCounter(&time);
138  return (double)(1000.0 * time.QuadPart / frequency.QuadPart);
139  }
140 #else
141  throw(vpException(vpException::fatalError, "Cannot get time: not implemented on Universal Windows Platform"));
142 #endif
143 #elif !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
144  struct timeval tp;
145  gettimeofday(&tp, 0);
146  return (1000.0 * tp.tv_sec + tp.tv_usec / 1000.0);
147 #endif
148 #endif
149 }
150 
156 double measureTimeSecond() { return vpTime::measureTimeMs() * 1e-3; }
157 
171 int wait(double t0, double t)
172 {
173  double timeCurrent, timeToWait;
174  timeCurrent = measureTimeMs();
175 
176  timeToWait = t0 + (t - timeCurrent);
177 
178  if (timeToWait <= 0.) { // no need to wait
179  return 1;
180  }
181  else {
182 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
183  if (timeToWait > vpTime::minTimeForUsleepCall) {
184  usleep(static_cast<useconds_t>((timeToWait - vpTime::minTimeForUsleepCall) * 1000));
185  }
186  // Blocking loop to have an accurate waiting
187  do {
188  timeCurrent = measureTimeMs();
189  timeToWait = t0 + (t - timeCurrent);
190 
191  } while (timeToWait > 0.);
192 
193  return 0;
194 #elif defined(_WIN32)
195 #if !defined(WINRT_8_0)
196  if (timeToWait > vpTime::minTimeForUsleepCall) {
197  Sleep((DWORD)(timeToWait - vpTime::minTimeForUsleepCall));
198  }
199  // Blocking loop to have an accurate waiting
200  do {
201  timeCurrent = measureTimeMs();
202  timeToWait = t0 + t - timeCurrent;
203 
204  } while (timeToWait > 0.);
205 
206  return 0;
207 #else
209  "vpTime::wait() is not implemented on Windows Phone 8.0"));
210 #endif
211 #endif
212  }
213 }
214 
223 void wait(double t)
224 {
225  double timeToWait = t;
226 
227  if (timeToWait <= 0.) { // no need to wait
228  return;
229  }
230  else {
231 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
232  double t0 = measureTimeMs();
233  if (timeToWait > vpTime::minTimeForUsleepCall) {
234  usleep(static_cast<useconds_t>((timeToWait - vpTime::minTimeForUsleepCall) * 1000));
235  }
236  // Blocking loop to have an accurate waiting
237  do {
238  double timeCurrent = measureTimeMs();
239  timeToWait = t0 + (t - timeCurrent);
240 
241  } while (timeToWait > 0.);
242 
243  return;
244 #elif defined(_WIN32)
245 #if !defined(WINRT_8_0)
246  double t0 = measureTimeMs();
247  if (timeToWait > vpTime::minTimeForUsleepCall) {
248  Sleep((DWORD)(timeToWait - vpTime::minTimeForUsleepCall));
249  }
250  // Blocking loop to have an accurate waiting
251  do {
252  double timeCurrent = measureTimeMs();
253  timeToWait = t0 + t - timeCurrent;
254 
255  } while (timeToWait > 0.);
256 
257  return;
258 #else
260  "vpTime::wait() is not implemented on Windows Phone 8.0"));
261 #endif
262 #endif
263  }
264 }
265 
271 void sleepMs(double t)
272 {
273 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
274  usleep(static_cast<useconds_t>(t * 1000));
275 #elif defined(_WIN32)
276 #if !defined(WINRT_8_0)
277  Sleep((DWORD)(t));
278 #else
280  "vpTime::sleepMs() is not implemented on Windows Phone 8.0"));
281 #endif
282 #endif
283 }
284 
361 std::string getDateTime(const std::string &format)
362 {
363  time_t rawtime;
364  struct tm *timeinfo;
365  char buffer[80];
366 
367  time(&rawtime);
368  timeinfo = localtime(&rawtime);
369 
370  strftime(buffer, 80, format.c_str(), timeinfo);
371  std::string str(buffer);
372 
373  return str;
374 }
375 
376 #ifndef DOXYGEN_SHOULD_SKIP_THIS
377 }
378 #endif
379 
380 vpChrono::vpChrono() : m_durationMs(), m_lastTimePoint() { }
381 
385 double vpChrono::getDurationMicros() { return m_durationMs * 1e3; }
386 
390 double vpChrono::getDurationMs() { return m_durationMs; }
391 
395 double vpChrono::getDurationSeconds() { return m_durationMs * 1e-3; }
396 
401 void vpChrono::start(bool reset)
402 {
403 #if USE_CXX11_CHRONO
404  m_lastTimePoint = std::chrono::steady_clock::now();
405 #else
406  m_lastTimePoint = vpTime::measureTimeMs();
407 #endif
408  if (reset) {
409  m_durationMs = 0.0;
410  }
411 }
412 
417 {
418 #if USE_CXX11_CHRONO
419  m_durationMs += std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - m_lastTimePoint).count();
420 #else
421  m_durationMs += vpTime::measureTimeMs() - m_lastTimePoint;
422 #endif
423 }
424 END_VISP_NAMESPACE
void start(bool reset=true)
Definition: vpTime.cpp:401
void stop()
Definition: vpTime.cpp:416
double getDurationSeconds()
Definition: vpTime.cpp:395
vpChrono()
Definition: vpTime.cpp:380
double getDurationMs()
Definition: vpTime.cpp:390
double getDurationMicros()
Definition: vpTime.cpp:385
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ functionNotImplementedError
Function not implemented.
Definition: vpException.h:66
@ fatalError
Fatal error.
Definition: vpException.h:72
Time management and measurement.
Definition: vpTime.h:78
VISP_EXPORT int wait(double t0, double t)
VISP_EXPORT double measureTimeMicros()
VISP_EXPORT double getMinTimeForUsleepCall()
VISP_EXPORT double measureTimeSecond()
VISP_EXPORT void sleepMs(double t)
VISP_EXPORT std::string getDateTime(const std::string &format="%Y/%m/%d %H:%M:%S")
VISP_EXPORT double measureTimeMs()