Visual Servoing Platform  version 3.6.0 under development (2023-09-29)
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  else {
182 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
183  if (timeToWait > vpTime::minTimeForUsleepCall) {
184  usleep((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  else {
230 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
231  double t0 = measureTimeMs();
232  if (timeToWait > vpTime::minTimeForUsleepCall) {
233  usleep((useconds_t)((timeToWait - vpTime::minTimeForUsleepCall) * 1000));
234  }
235  // Blocking loop to have an accurate waiting
236  do {
237  double timeCurrent = measureTimeMs();
238  timeToWait = t0 + t - timeCurrent;
239 
240  } while (timeToWait > 0.);
241 
242  return;
243 #elif defined(_WIN32)
244 #if !defined(WINRT_8_0)
245  double t0 = measureTimeMs();
246  if (timeToWait > vpTime::minTimeForUsleepCall) {
247  Sleep((DWORD)(timeToWait - vpTime::minTimeForUsleepCall));
248  }
249  // Blocking loop to have an accurate waiting
250  do {
251  double timeCurrent = measureTimeMs();
252  timeToWait = t0 + t - timeCurrent;
253 
254  } while (timeToWait > 0.);
255 
256  return;
257 #else
259  "vpTime::wait() is not implemented on Windows Phone 8.0"));
260 #endif
261 #endif
262  }
263 }
264 
270 void sleepMs(double t)
271 {
272 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
273  usleep((useconds_t)(t * 1000));
274 #elif defined(_WIN32)
275 #if !defined(WINRT_8_0)
276  Sleep((DWORD)(t));
277 #else
279  "vpTime::sleepMs() is not implemented on Windows Phone 8.0"));
280 #endif
281 #endif
282 }
283 
357 std::string getDateTime(const std::string &format)
358 {
359  time_t rawtime;
360  struct tm *timeinfo;
361  char buffer[80];
362 
363  time(&rawtime);
364  timeinfo = localtime(&rawtime);
365 
366  strftime(buffer, 80, format.c_str(), timeinfo);
367  std::string str(buffer);
368 
369  return str;
370 }
371 
372 #ifndef DOXYGEN_SHOULD_SKIP_THIS
373 };
374 #endif
375 
376 vpChrono::vpChrono() : m_durationMs(), m_lastTimePoint() { }
377 
381 double vpChrono::getDurationMicros() { return m_durationMs * 1e3; }
382 
386 double vpChrono::getDurationMs() { return m_durationMs; }
387 
391 double vpChrono::getDurationSeconds() { return m_durationMs * 1e-3; }
392 
397 void vpChrono::start(bool reset)
398 {
399 #if USE_CXX11_CHRONO
400  m_lastTimePoint = std::chrono::steady_clock::now();
401 #else
402  m_lastTimePoint = vpTime::measureTimeMs();
403 #endif
404  if (reset) {
405  m_durationMs = 0.0;
406  }
407 }
408 
413 {
414 #if USE_CXX11_CHRONO
415  m_durationMs += std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - m_lastTimePoint).count();
416 #else
417  m_durationMs += vpTime::measureTimeMs() - m_lastTimePoint;
418 #endif
419 }
void start(bool reset=true)
Definition: vpTime.cpp:397
void stop()
Definition: vpTime.cpp:412
double getDurationSeconds()
Definition: vpTime.cpp:391
vpChrono()
Definition: vpTime.cpp:376
double getDurationMs()
Definition: vpTime.cpp:386
double getDurationMicros()
Definition: vpTime.cpp:381
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:73
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()