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