Simbody  3.6
Timing.h
Go to the documentation of this file.
1 #ifndef SimTK_SimTKCOMMON_TIMING_H_
2 #define SimTK_SimTKCOMMON_TIMING_H_
3 
4 /* -------------------------------------------------------------------------- *
5  * Simbody(tm): SimTKcommon *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from *
8  * Simbios, the NIH National Center for Physics-Based Simulation of *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11  * *
12  * Portions copyright (c) 2010-12 Stanford University and the Authors. *
13  * Authors: Michael Sherman *
14  * Contributors: *
15  * *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17  * not use this file except in compliance with the License. You may obtain a *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19  * *
20  * Unless required by applicable law or agreed to in writing, software *
21  * distributed under the License is distributed on an "AS IS" BASIS, *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23  * See the License for the specific language governing permissions and *
24  * limitations under the License. *
25  * -------------------------------------------------------------------------- */
26 
52 #include "SimTKcommon/Constants.h"
53 
54 // This header is needed on Mac and Linux for some or all of the Posix time
55 // functions and the timespec struct. We include it on Windows also for
56 // uniform cross-platform behavior, since there are many other useful time-
57 // date-handling symbols declared here on all platforms.
58 #include <ctime>
59 
60 
61 // macOS (OSX) 10.12 introduced support for clock_gettime().
62 // The following logic is based on documentation in /usr/local/Availability.h
63 // and from this site:
64 // https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/cross_development/Using/using.html.
65 // This website also recommends using Availability.h over the similarly-helpful
66 // AvailabilityMacros.h.
67 #if defined(__APPLE__)
68  #include <Availability.h>
69 #endif
70 // We'll use the following macros throughout Timing.(h|cpp).
71 // "MAX_ALLOWED" is the version of the OSX SDK used when building.
72 // "MIN_REQUIRED" is the "DEPLOYMENT_TARGET": earliest version on which the
73 // binaries should run.
74 // One can use the 10.12 SDK to deploy to earlier releases, like 10.11. The SDK
75 // version determines if we need to declare clock_gettime() (e.g., developer is
76 // using an SDK older than 10.12), and the deployment target determines if we
77 // cannot expect the user's system to contain an implementation of
78 // clock_gettime() (e.g., user may be running an on OS older than 10.12).
79 // We need both of these macros because developers may only have the 10.12 SDK,
80 // but may want to use it to deploy to machines running 10.11. In such a case,
81 // we cannot declare clock_gettime() ourselves (the SDK does it), but we must
82 // still define it.
83 // The number 101200 identifies macOS version 10.12. The explicit version
84 // number must be used instead of a macro like __MAC_10_12 because pre-10.12
85 // systems won't have __MAC_10_12 defined.
86 #if defined(__APPLE__) && __MAC_OS_X_VERSION_MAX_ALLOWED < 101200
87  // SDK is older than 10.12.
88  #define SimTK_IS_APPLE_AND_MUST_DECLARE_CLOCK_GETTIME 1
89 #else
90  #define SimTK_IS_APPLE_AND_MUST_DECLARE_CLOCK_GETTIME 0
91 #endif
92 
93 #if defined(__APPLE__) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200
94  // user's OS may be pre-10.12.
95  #define SimTK_IS_APPLE_AND_MUST_DEFINE_CLOCK_GETTIME 1
96 #else
97  #define SimTK_IS_APPLE_AND_MUST_DEFINE_CLOCK_GETTIME 0
98 #endif
99 
100 
101 
102 #if defined(_MSC_VER)
103  /* Posix nanosleep() sleeps the indicated number of nanoseconds and returns
104  0, or if it is interrupted early it returns how much time was left in
105  rem and returns EINTR. Ours is not interruptable so will always succeed and
106  return rem==0. It is OK if rem is NULL, but req==NULL or req<0 returns
107  EINVAL. A time of req==0 is allowed and our interpretation is that the
108  thread relinquishes its time slice to another ready-to-run thread if there
109  is one, otherwise returns immediately. This implementation rounds the
110  desired sleep time to the nearest millisecond. On a Linux system, this
111  requires including <time.h> (or <ctime>), which we already included
112  above. */
113  SimTK_SimTKCOMMON_EXPORT int nanosleep(const struct timespec* req, struct timespec* rem);
114 
115  /* Posix declares this handy function obsolete, but I don't think it is in
116  any danger of going away. It sleeps for the given number of microseconds.
117  However, using SimTK::sleepInNs() or SimTK::sleepInSec() is safer. */
118  typedef unsigned int useconds_t;
119  inline int usleep(useconds_t us) {
120  struct timespec req;
121  req.tv_sec = (long) (us / 1000000U);
122  req.tv_nsec = (long)((us % 1000000U)*1000U);
123  int status = nanosleep(&req,0);
124  return status ? -1 : 0;
125  }
126 #endif
127 
128 #if defined(_MSC_VER) || SimTK_IS_APPLE_AND_MUST_DECLARE_CLOCK_GETTIME
129  // On Windows and OSX < 10.12, the Posix clock_gettime function is missing.
130  typedef long clockid_t;
131 
132  /* These constants are the clock ids we support. All the varieties of
133  CLOCK_MONOTONIC are high resolution with no NTP adjustments. I measured
134  the resolutions on a single Windows 7 machine; hopefully they are typical
135  (resolution here means how often they are updated):
136  - MONOTONIC (counter): 0.001ms 1us
137  - REALTIME (time of day): 1ms 1000us
138  - CPUTIME (either): 20ms 20000us
139  These are slightly conservative resolutions so you should be able to
140  achieve them in practice. */
141  #define CLOCK_REALTIME 1 // time of day clock, from 1/1/1970
142  #define CLOCK_MONOTONIC 2 // counter from last boot time
143  #define CLOCK_MONOTONIC_HR 3 // "high resolution" (same)
144  #define CLOCK_MONOTONIC_RAW 4 // "not subject to NTP adjustments" (same)
145  #define CLOCK_THREAD_CPUTIME_ID 5 // current thread's cpu time (kernel+user)
146  #define CLOCK_PROCESS_CPUTIME_ID 6 // cumulative cpu time of all threads of
147  // this process, live or dead
148 
149  /* Returns zero if it succeeds (or if tp==NULL); otherwise EINVAL. On a
150  Linux system, this requires including <time.h> (or <ctime>) and linking
151  with -lrt to get the realtime library. */
152  SimTK_SimTKCOMMON_EXPORT int clock_gettime(clockid_t clock_id,
153  struct timespec *tp);
154 #endif
155 
156 
157 
158 namespace SimTK {
159 
186 inline long long timespecToNs(const timespec& ts)
187 { return (long long)ts.tv_sec*1000000000LL + (long long)ts.tv_nsec; }
188 
191 inline void nsToTimespec(const long long& ns, timespec& ts)
192 { ts.tv_sec = (long)(ns / 1000000000LL); // signed
193  if (ns >= 0) ts.tv_nsec = (long)( ns % 1000000000LL);
194  else ts.tv_nsec = -(long)((-ns) % 1000000000LL); }
195 
199 inline double nsToSec(const long long& ns)
200 { return (double)(ns*SimTK_NS_TO_S); }
201 
205 inline long long secToNs(const double& s)
206 { return (long long)(s*SimTK_S_TO_NS); }
228 inline double cpuTime()
229 { timespec ts;
230  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
231  return (double)(timespecToNs(ts)*SimTK_NS_TO_S); }
232 
239 inline double threadCpuTime()
240 { timespec ts;
241  clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
242  return (double)(timespecToNs(ts)*SimTK_NS_TO_S); }
273 inline long long realTimeInNs() {
274  timespec ts;
275  #ifdef CLOCK_MONOTONIC_RAW
276  clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
277  #else
278  clock_gettime(CLOCK_MONOTONIC, &ts);
279  #endif
280  return timespecToNs(ts);
281 }
282 
290 inline double realTime() {return nsToSec(realTimeInNs());}
291 
299 inline void sleepInNs(const long long& ns)
300 { timespec ts;
301  nsToTimespec(ns, ts);
302  nanosleep(&ts, 0); }
303 
311 inline void sleepInSec(const double& seconds) {sleepInNs(secToNs(seconds));}
314 } // namespace SimTK
315 
316 #endif // SimTK_SimTKCOMMON_TIMING_H_
#define SimTK_SimTKCOMMON_EXPORT
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:224
long long secToNs(const double &s)
Given a signed time interval as a double precision floating point number of seconds, return the same time interval as a count of nanosecond ticks in a signed 64 bit integer.
Definition: Timing.h:205
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition: Assembler.h:37
double cpuTime()
Return the cumulative CPU time in seconds (both kernel and user time) that has been used so far by an...
Definition: Timing.h:228
void nsToTimespec(const long long &ns, timespec &ts)
Given a signed number of nanoseconds, convert that into seconds and leftover nanoseconds in a timespe...
Definition: Timing.h:191
double realTime()
Return current time on the high-resolution interval timer in seconds.
Definition: Timing.h:290
void sleepInNs(const long long &ns)
Sleep for the indicated number of nanoseconds, with the actual precision system dependent but intende...
Definition: Timing.h:299
long long timespecToNs(const timespec &ts)
Convert a time stored in a timespec struct to the equivalent number of nanoseconds (as a signed quant...
Definition: Timing.h:186
High precision mathematical and physical constants.
void sleepInSec(const double &seconds)
Sleep for the indicated number of seconds, with the actual precision system dependent but intended to...
Definition: Timing.h:311
double nsToSec(const long long &ns)
Given a count of nanosecond ticks as a signed 64 bit integer, return the same time interval as a doub...
Definition: Timing.h:199
Mandatory first inclusion for any Simbody source or header file.
#define SimTK_NS_TO_S
Convert nanoseconds to seconds.
Definition: Constants.h:527
#define SimTK_S_TO_NS
Convert seconds to nanoseconds.
Definition: Constants.h:535
double threadCpuTime()
Return the total CPU time in seconds (both kernel and user time) that has been used so far by the cur...
Definition: Timing.h:239
long long realTimeInNs()
Return current time on the high-resolution interval timer in nanoseconds, as a 64-bit integer count...
Definition: Timing.h:273