3636
3737#include " syspovtimer.h"
3838
39+ #include < cerrno>
3940#include < ctime>
4041
4142#ifdef HAVE_UNISTD_H
@@ -69,24 +70,47 @@ namespace pov_base
6970
7071// ******************************************************************************
7172
72- #if !POV_USE_DEFAULT_DELAY
73+ #if (POV_USE_PLATFORM_DELAY == 1)
7374
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.
7478void Delay (unsigned int msec)
7579{
76- #if defined(HAVE_NANOSLEEP)
77- timespec ts;
80+ timespec ts, remain;
7881 ts.tv_sec = msec / 1000 ;
7982 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 );
87107}
88108
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
90114
91115// ******************************************************************************
92116
@@ -138,9 +162,11 @@ static inline bool GettimeofdayMillisec(POV_ULONG& result)
138162}
139163
140164Timer::Timer () :
165+ #if !POVUNIX_USE_DEFAULT_REAL_TIMER
141166 mWallTimeUseClockGettimeMonotonic (false ),
142167 mWallTimeUseClockGettimeRealtime (false ),
143168 mWallTimeUseGettimeofday (false ),
169+ #endif
144170 mProcessTimeUseGetrusageSelf (false ),
145171 mProcessTimeUseClockGettimeProcess (false ),
146172 mProcessTimeUseFallback (false ),
@@ -149,6 +175,7 @@ Timer::Timer () :
149175 mThreadTimeUseClockGettimeThread (false ),
150176 mThreadTimeUseFallback (false )
151177{
178+ #if !POVUNIX_USE_DEFAULT_REAL_TIMER
152179 // Figure out which timer source to use for wall clock time.
153180 bool haveWallTime = false ;
154181#if defined(HAVE_DECL_CLOCK_MONOTONIC) && HAVE_DECL_CLOCK_MONOTONIC
@@ -165,12 +192,13 @@ Timer::Timer () :
165192 // gettimeofday(), and document it here.
166193 if (!haveWallTime)
167194 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
169196 if (!haveWallTime)
170197 {
171198 POV_ASSERT (false );
172199 mWallTimeStart = 0 ;
173200 }
201+ #endif
174202
175203 // Figure out which timer source to use for per-process CPU time.
176204 bool haveProcessTime = false ;
@@ -186,8 +214,12 @@ Timer::Timer () :
186214#endif
187215 if (!haveProcessTime)
188216 {
217+ #if POVUNIX_USE_DEFAULT_REAL_TIMER
218+ haveProcessTime = mProcessTimeUseFallback = true ;
219+ #else
189220 haveProcessTime = mProcessTimeUseFallback = haveWallTime;
190221 mProcessTimeStart = mWallTimeStart ;
222+ #endif
191223 }
192224
193225 // Figure out which timer source to use for per-thread CPU time.
@@ -212,11 +244,7 @@ Timer::Timer () :
212244 }
213245}
214246
215- Timer::~Timer ()
216- {
217- // nothing to do
218- }
219-
247+ #if !POVUNIX_USE_DEFAULT_REAL_TIMER
220248POV_ULONG Timer::GetWallTime () const
221249{
222250 POV_ULONG result;
@@ -232,6 +260,7 @@ POV_ULONG Timer::GetWallTime () const
232260 return (GettimeofdayMillisec (result) ? result : 0 );
233261 return 0 ;
234262}
263+ #endif
235264
236265POV_ULONG Timer::GetProcessTime () const
237266{
@@ -245,7 +274,11 @@ POV_ULONG Timer::GetProcessTime () const
245274 return (ClockGettimeMillisec (result, CLOCK_PROCESS_CPUTIME_ID) ? result : 0 );
246275#endif
247276 if (mProcessTimeUseFallback )
277+ #if POVUNIX_USE_DEFAULT_REAL_TIMER
278+ return mRealTimer .ElapsedTime ();
279+ #else
248280 return GetWallTime ();
281+ #endif
249282 return 0 ;
250283}
251284
@@ -269,10 +302,12 @@ POV_ULONG Timer::GetThreadTime () const
269302 return 0 ;
270303}
271304
305+ #if !POVUNIX_USE_DEFAULT_REAL_TIMER
272306POV_LONG Timer::ElapsedRealTime () const
273307{
274308 return GetWallTime () - mWallTimeStart ;
275309}
310+ #endif
276311
277312POV_LONG Timer::ElapsedProcessCPUTime () const
278313{
@@ -286,7 +321,11 @@ POV_LONG Timer::ElapsedThreadCPUTime () const
286321
287322void Timer::Reset ()
288323{
324+ #if POVUNIX_USE_DEFAULT_REAL_TIMER
325+ mRealTimer .Reset ();
326+ #else
289327 mWallTimeStart = GetWallTime ();
328+ #endif
290329 mProcessTimeStart = GetProcessTime ();
291330 mThreadTimeStart = GetThreadTime ();
292331}
0 commit comments