Visual Servoing Platform  version 3.6.1 under development (2024-04-19)
vpTime.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 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 https://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 *****************************************************************************/
35 
36 #include <ctime>
37 
38 #include <visp3/core/vpDebug.h>
39 #include <visp3/core/vpTime.h>
40 
41 // https://devblogs.microsoft.com/cppblog/c14-stl-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1/
42 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11) && \
43  (defined(_MSC_VER) && _MSC_VER >= 1900 /* VS2015 */ || !defined(_MSC_VER))
44 #define USE_CXX11_CHRONO 1
45 #else
46 #define USE_CXX11_CHRONO 0
47 #endif
48 
54 // Unix depend version
55 
56 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
57 #include <sys/time.h>
58 #include <unistd.h>
59 #elif defined(_WIN32)
60 //#include <winbase.h>
61 #include <windows.h>
62 #endif
63 
64 #ifndef DOXYGEN_SHOULD_SKIP_THIS
65 namespace vpTime
66 {
67 #endif
68 
76 static const double minTimeForUsleepCall = 4;
77 
83 double getMinTimeForUsleepCall() { return minTimeForUsleepCall; }
84 
90 double measureTimeMicros()
91 {
92 #if USE_CXX11_CHRONO
93  std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
94  return std::chrono::duration<double, std::micro>(now.time_since_epoch()).count();
95 #else
96 #if defined(_WIN32)
97 #if !defined(WINRT)
98  LARGE_INTEGER time, frequency;
99  QueryPerformanceFrequency(&frequency);
100  if (frequency.QuadPart == 0) {
101  return (timeGetTime());
102  }
103  else {
104  QueryPerformanceCounter(&time);
105  return (double)(1000000.0 * time.QuadPart / frequency.QuadPart);
106  }
107 #else
108  throw(vpException(vpException::fatalError, "Cannot get time: not implemented on Universal Windows Platform"));
109 #endif
110 #elif !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
111  struct timeval tp;
112  gettimeofday(&tp, 0);
113  return (1000000.0 * tp.tv_sec + tp.tv_usec);
114 #endif
115 #endif
116 }
117 
124 double measureTimeMs()
125 {
126 #if USE_CXX11_CHRONO
127  std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
128  return std::chrono::duration<double, std::milli>(now.time_since_epoch()).count();
129 #else
130 #if defined(_WIN32)
131 #if !defined(WINRT)
132  LARGE_INTEGER time, frequency;
133  QueryPerformanceFrequency(&frequency);
134  if (frequency.QuadPart == 0) {
135  return (timeGetTime());
136  }
137  else {
138  QueryPerformanceCounter(&time);
139  return (double)(1000.0 * time.QuadPart / frequency.QuadPart);
140  }
141 #else
142  throw(vpException(vpException::fatalError, "Cannot get time: not implemented on Universal Windows Platform"));
143 #endif
144 #elif !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
145  struct timeval tp;
146  gettimeofday(&tp, 0);
147  return (1000.0 * tp.tv_sec + tp.tv_usec / 1000.0);
148 #endif
149 #endif
150 }
151 
157 double measureTimeSecond() { return vpTime::measureTimeMs() * 1e-3; }
158 
172 int wait(double t0, double t)
173 {
174  double timeCurrent, timeToWait;
175  timeCurrent = measureTimeMs();
176 
177  timeToWait = t0 + (t - timeCurrent);
178 
179  if (timeToWait <= 0.) { // no need to wait
180  return 1;
181  }
182  else {
183 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
184  if (timeToWait > vpTime::minTimeForUsleepCall) {
185  usleep(static_cast<useconds_t>((timeToWait - vpTime::minTimeForUsleepCall) * 1000));
186  }
187  // Blocking loop to have an accurate waiting
188  do {
189  timeCurrent = measureTimeMs();
190  timeToWait = t0 + (t - timeCurrent);
191 
192  } while (timeToWait > 0.);
193 
194  return 0;
195 #elif defined(_WIN32)
196 #if !defined(WINRT_8_0)
197  if (timeToWait > vpTime::minTimeForUsleepCall) {
198  Sleep((DWORD)(timeToWait - vpTime::minTimeForUsleepCall));
199  }
200  // Blocking loop to have an accurate waiting
201  do {
202  timeCurrent = measureTimeMs();
203  timeToWait = t0 + t - timeCurrent;
204 
205  } while (timeToWait > 0.);
206 
207  return 0;
208 #else
210  "vpTime::wait() is not implemented on Windows Phone 8.0"));
211 #endif
212 #endif
213  }
214 }
215 
224 void wait(double t)
225 {
226  double timeToWait = t;
227 
228  if (timeToWait <= 0.) { // no need to wait
229  return;
230  }
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(static_cast<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(static_cast<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 emitted by ViSP classes.
Definition: vpException.h:59
@ functionNotImplementedError
Function not implemented.
Definition: vpException.h:78
@ fatalError
Fatal error.
Definition: vpException.h:84
Time management and measurement.
Definition: vpTime.h:72
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()