36
36
37
37
#include " syspovtimer.h"
38
38
39
+ #include < cerrno>
39
40
#include < ctime>
40
41
41
42
#ifdef HAVE_UNISTD_H
@@ -69,24 +70,47 @@ namespace pov_base
69
70
70
71
// ******************************************************************************
71
72
72
- #if !POV_USE_DEFAULT_DELAY
73
+ #if (POV_USE_PLATFORM_DELAY == 1)
73
74
75
+ // NOTE: Even if we decide to discontinue the use of this implementation,
76
+ // we may want to keep it around in case it may turn out to be superior on some
77
+ // exotic systems.
74
78
void Delay (unsigned int msec)
75
79
{
76
- #if defined(HAVE_NANOSLEEP)
77
- timespec ts;
80
+ timespec ts, remain;
78
81
ts.tv_sec = msec / 1000 ;
79
82
ts.tv_nsec = (POV_ULONG) (1000000 ) * (msec % 1000 );
80
- nanosleep (&ts, nullptr );
81
- #elif defined(HAVE_USLEEP)
82
- POV_ASSERT (msec < 1000 ); // On some systems, usleep() does not support sleeping for 1 second or more.
83
- usleep (msec * (useconds_t )1000 );
84
- #else
85
- #error "Bad compile-time configuration."
86
- #endif
83
+ errno = 0 ;
84
+ while ((nanosleep (&ts, &remain) != 0 ) && (errno == EINTR))
85
+ {
86
+ ts = remain;
87
+ errno = 0 ;
88
+ }
89
+ }
90
+
91
+ #elif (POV_USE_PLATFORM_DELAY == 2)
92
+
93
+ // ATTENTION: According to the POSIX standard, `usleep()` need not be
94
+ // thread-safe!
95
+
96
+ // NOTE: Although we're currently not using this implementation, we may want to
97
+ // keep it around in case we find the default implementation wanting on some
98
+ // systems.
99
+ void Delay (unsigned int msec)
100
+ {
101
+ // According to the POSIX standard, `usleep()` may not support parameter
102
+ // values of 1 million or higher (corresponding to 1s). We work around this
103
+ // by simply calling `usleep()` repeatedly until we're good.
104
+ for (unsigned int sec = 0 ; sec < (msec/1000 ); ++sec)
105
+ usleep ((useconds_t )999999 ); // not exactly 1s, but close enough.
106
+ usleep ((msec % 1000 ) * (useconds_t )1000 );
87
107
}
88
108
89
- #endif // !POV_USE_DEFAULT_DELAY
109
+ #else // POV_USE_PLATFORM_DELAY
110
+
111
+ #error "Bad compile-time configuration."
112
+
113
+ #endif // POV_USE_PLATFORM_DELAY
90
114
91
115
// ******************************************************************************
92
116
@@ -138,9 +162,11 @@ static inline bool GettimeofdayMillisec(POV_ULONG& result)
138
162
}
139
163
140
164
Timer::Timer () :
165
+ #if !POVUNIX_USE_DEFAULT_REAL_TIMER
141
166
mWallTimeUseClockGettimeMonotonic (false ),
142
167
mWallTimeUseClockGettimeRealtime (false ),
143
168
mWallTimeUseGettimeofday (false ),
169
+ #endif
144
170
mProcessTimeUseGetrusageSelf (false ),
145
171
mProcessTimeUseClockGettimeProcess (false ),
146
172
mProcessTimeUseFallback (false ),
@@ -149,6 +175,7 @@ Timer::Timer () :
149
175
mThreadTimeUseClockGettimeThread (false ),
150
176
mThreadTimeUseFallback (false )
151
177
{
178
+ #if !POVUNIX_USE_DEFAULT_REAL_TIMER
152
179
// Figure out which timer source to use for wall clock time.
153
180
bool haveWallTime = false ;
154
181
#if defined(HAVE_DECL_CLOCK_MONOTONIC) && HAVE_DECL_CLOCK_MONOTONIC
@@ -165,12 +192,13 @@ Timer::Timer () :
165
192
// gettimeofday(), and document it here.
166
193
if (!haveWallTime)
167
194
haveWallTime = mWallTimeUseGettimeofday = GettimeofdayMillisec (mWallTimeStart );
168
- // FIXME: add fallback, using ftime(), or time() + a counter for ms, or maybe boost::date_time
195
+ // FIXME: add fallback, using ftime(), or time() + a counter for ms, or maybe std::chrono
169
196
if (!haveWallTime)
170
197
{
171
198
POV_ASSERT (false );
172
199
mWallTimeStart = 0 ;
173
200
}
201
+ #endif
174
202
175
203
// Figure out which timer source to use for per-process CPU time.
176
204
bool haveProcessTime = false ;
@@ -186,8 +214,12 @@ Timer::Timer () :
186
214
#endif
187
215
if (!haveProcessTime)
188
216
{
217
+ #if POVUNIX_USE_DEFAULT_REAL_TIMER
218
+ haveProcessTime = mProcessTimeUseFallback = true ;
219
+ #else
189
220
haveProcessTime = mProcessTimeUseFallback = haveWallTime;
190
221
mProcessTimeStart = mWallTimeStart ;
222
+ #endif
191
223
}
192
224
193
225
// Figure out which timer source to use for per-thread CPU time.
@@ -212,11 +244,7 @@ Timer::Timer () :
212
244
}
213
245
}
214
246
215
- Timer::~Timer ()
216
- {
217
- // nothing to do
218
- }
219
-
247
+ #if !POVUNIX_USE_DEFAULT_REAL_TIMER
220
248
POV_ULONG Timer::GetWallTime () const
221
249
{
222
250
POV_ULONG result;
@@ -232,6 +260,7 @@ POV_ULONG Timer::GetWallTime () const
232
260
return (GettimeofdayMillisec (result) ? result : 0 );
233
261
return 0 ;
234
262
}
263
+ #endif
235
264
236
265
POV_ULONG Timer::GetProcessTime () const
237
266
{
@@ -245,7 +274,11 @@ POV_ULONG Timer::GetProcessTime () const
245
274
return (ClockGettimeMillisec (result, CLOCK_PROCESS_CPUTIME_ID) ? result : 0 );
246
275
#endif
247
276
if (mProcessTimeUseFallback )
277
+ #if POVUNIX_USE_DEFAULT_REAL_TIMER
278
+ return mRealTimer .ElapsedTime ();
279
+ #else
248
280
return GetWallTime ();
281
+ #endif
249
282
return 0 ;
250
283
}
251
284
@@ -269,10 +302,12 @@ POV_ULONG Timer::GetThreadTime () const
269
302
return 0 ;
270
303
}
271
304
305
+ #if !POVUNIX_USE_DEFAULT_REAL_TIMER
272
306
POV_LONG Timer::ElapsedRealTime () const
273
307
{
274
308
return GetWallTime () - mWallTimeStart ;
275
309
}
310
+ #endif
276
311
277
312
POV_LONG Timer::ElapsedProcessCPUTime () const
278
313
{
@@ -286,7 +321,11 @@ POV_LONG Timer::ElapsedThreadCPUTime () const
286
321
287
322
void Timer::Reset ()
288
323
{
324
+ #if POVUNIX_USE_DEFAULT_REAL_TIMER
325
+ mRealTimer .Reset ();
326
+ #else
289
327
mWallTimeStart = GetWallTime ();
328
+ #endif
290
329
mProcessTimeStart = GetProcessTime ();
291
330
mThreadTimeStart = GetThreadTime ();
292
331
}
0 commit comments