2 * @brief Functions for handling a time or time interval in a double.
4 /* Copyright (C) 2010,2011,2013,2014,2015,2020 Olly Betts
6 * This program 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.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifndef XAPIAN_INCLUDED_REALTIME_H
22 #define XAPIAN_INCLUDED_REALTIME_H
25 # error config.h must be included first in each C++ source file
34 # include <sys/timeb.h>
36 # ifdef HAVE_GETTIMEOFDAY
37 # include <sys/time.h>
39 # include "safesysselect.h"
41 # include <sys/types.h>
42 # include <sys/timeb.h>
43 extern void xapian_sleep_milliseconds(unsigned int millisecs
);
48 /// Return the current time.
50 #if defined HAVE_CLOCK_GETTIME
51 // We prefer functions which can return the time with a higher precision.
52 // On POSIX platforms that means we prefer clock_gettime() over
53 // gettimeofday() over ftime().
55 // (Also, POSIX.1-2008 stopped specifying ftime(), and marked gettimeofday()
56 // as obsolete, recommending clock_gettime() instead.)
58 // Modern mingw provides clock_gettime(). For older mingw and MSVC we fall
59 // back to _ftime64().
61 if (usual(clock_gettime(CLOCK_REALTIME
, &ts
) == 0))
62 return ts
.tv_sec
+ (ts
.tv_nsec
* 1e-9);
63 return double(std::time(NULL
));
64 #elif !defined __WIN32__
65 # if defined HAVE_GETTIMEOFDAY
67 if (usual(gettimeofday(&tv
, NULL
) == 0))
68 return tv
.tv_sec
+ (tv
.tv_usec
* 1e-6);
69 return double(std::time(NULL
));
70 # elif defined HAVE_FTIME
72 # ifdef FTIME_RETURNS_VOID
75 if (rare(ftime(&tp
) != 0))
76 return double(std::time(NULL
));
78 return tp
.time
+ (tp
.millitm
* 1e-3);
80 return double(std::time(NULL
));
86 return tp
.time
+ tp
.millitm
* 1e-3;
90 /** Return the end time for a timeout in @a timeout seconds.
92 * If @a timeout is 0, that means "no timeout", so 0 is returned. Otherwise
93 * the current time plus @a timeout seconds is returned.
95 inline double end_time(double timeout
) {
96 return (timeout
== 0.0 ? timeout
: timeout
+ now());
99 #if defined HAVE_NANOSLEEP || defined HAVE_TIMER_CREATE
100 /// Fill in struct timespec from number of seconds in a double.
101 inline void to_timespec(double t
, struct timespec
*ts
) {
103 ts
->tv_nsec
= long(std::modf(t
, &secs
) * 1e9
);
104 ts
->tv_sec
= long(secs
);
108 /// Fill in struct timeval from number of seconds in a double.
110 inline void to_timeval(double t
, struct timeval
*tv
) {
112 tv
->tv_usec
= long(std::modf(t
, &secs
) * 1e6
);
113 tv
->tv_sec
= long(secs
);
116 // Use a macro to avoid having to pull in winsock2.h just for struct timeval.
117 # define to_timeval(T, TV) to_timeval_((T), (TV)->tv_sec, (TV)->tv_usec)
119 inline void to_timeval_(double t
, long & tv_sec
, long & tv_usec
) {
121 tv_usec
= long(std::modf(t
, &secs
) * 1e6
);
126 /// Sleep until the time represented by this object.
127 inline void sleep(double t
) {
128 #ifdef HAVE_NANOSLEEP
129 // Available on modern POSIX systems and under modern mingw.
130 double delta
= t
- RealTime::now();
134 to_timespec(delta
, &ts
);
135 while (nanosleep(&ts
, &ts
) < 0 && errno
== EINTR
) { }
136 #elif !defined __WIN32__
140 delta
= t
- RealTime::now();
143 to_timeval(delta
, &tv
);
144 } while (select(0, NULL
, NULL
, NULL
, &tv
) < 0 &&
145 (errno
== EINTR
|| errno
== EAGAIN
));
147 double delta
= t
- RealTime::now();
150 while (rare(delta
> 4294967.0)) {
151 xapian_sleep_milliseconds(4294967000u);
154 xapian_sleep_milliseconds(unsigned(delta
* 1000.0));
160 #endif // XAPIAN_INCLUDED_REALTIME_H