Support: quest -f cjk_ngram
[xapian.git] / xapian-core / common / realtime.h
blob7866338f4fffca369c2ed71571c40fbef6b3505f
1 /** @file realtime.h
2 * @brief Functions for handling a time or time interval in a double.
3 */
4 /* Copyright (C) 2010,2011,2013,2014,2015 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
24 #include <cmath>
25 #include <ctime>
26 #include "safeerrno.h"
28 #ifndef __WIN32__
29 # ifdef HAVE_FTIME
30 # include <sys/timeb.h>
31 # endif
32 # ifdef HAVE_GETTIMEOFDAY
33 # include <sys/time.h>
34 # endif
35 # include "safesysselect.h"
36 #else
37 # include <sys/types.h>
38 # include <sys/timeb.h>
39 extern void xapian_sleep_milliseconds(unsigned int millisecs);
40 #endif
42 namespace RealTime {
44 /// Return the current time.
45 inline double now() {
46 #ifndef __WIN32__
47 // We prefer clock_gettime() over gettimeofday() over ftime(). This order
48 // favours functions which can return the time with a higher precision.
50 // Also, POSIX.1-2008 stopped specifying ftime(), and marked gettimeofday()
51 // as obsolete, recommending clock_gettime() instead.
52 # if defined HAVE_CLOCK_GETTIME
53 struct timespec ts;
54 if (usual(clock_gettime(CLOCK_REALTIME, &ts) == 0))
55 return ts.tv_sec + (ts.tv_nsec * 1e-9);
56 return double(std::time(NULL));
57 # elif defined HAVE_GETTIMEOFDAY
58 struct timeval tv;
59 if (usual(gettimeofday(&tv, NULL) == 0))
60 return tv.tv_sec + (tv.tv_usec * 1e-6);
61 return double(std::time(NULL));
62 # elif defined HAVE_FTIME
63 struct timeb tp;
64 # ifdef FTIME_RETURNS_VOID
65 ftime(&tp);
66 # else
67 if (rare(ftime(&tp) != 0))
68 return double(std::time(NULL));
69 # endif
70 return tp.time + (tp.millitm * 1e-3);
71 # else
72 return double(std::time(NULL));
73 # endif
74 #else
75 struct __timeb64 tp;
76 _ftime64(&tp);
77 return tp.time + tp.millitm * 1e-3;
78 #endif
81 /** Return the end time for a timeout in @a timeout seconds.
83 * If @a timeout is 0, that means "no timeout", so 0 is returned. Otherwise
84 * the current time plus @a timeout seconds is returned.
86 inline double end_time(double timeout) {
87 return (timeout == 0.0 ? timeout : timeout + now());
90 #ifndef __WIN32__
91 # if defined HAVE_NANOSLEEP || defined HAVE_TIMER_CREATE
92 /// Fill in struct timespec from number of seconds in a double.
93 inline void to_timespec(double t, struct timespec *ts) {
94 double secs;
95 ts->tv_nsec = long(std::modf(t, &secs) * 1e9);
96 ts->tv_sec = long(secs);
98 # endif
100 /// Fill in struct timeval from number of seconds in a double.
101 inline void to_timeval(double t, struct timeval *tv) {
102 double secs;
103 tv->tv_usec = long(std::modf(t, &secs) * 1e6);
104 tv->tv_sec = long(secs);
106 #else
107 // Use a macro to avoid having to pull in winsock2.h just for struct timeval.
108 #define to_timeval(T, TV) to_timeval_((T), (TV)->tv_sec, (TV)->tv_usec)
109 inline void to_timeval_(double t, long & tv_sec, long & tv_usec) {
110 double secs;
111 tv_usec = long(std::modf(t, &secs) * 1e6);
112 tv_sec = long(secs);
114 #endif
116 /// Sleep until the time represented by this object.
117 inline void sleep(double t) {
118 #ifndef __WIN32__
119 # ifdef HAVE_NANOSLEEP
120 double delta = t - RealTime::now();
121 if (delta <= 0.0)
122 return;
123 struct timespec ts;
124 to_timespec(delta, &ts);
125 while (nanosleep(&ts, &ts) < 0 && errno == EINTR) { }
126 # else
127 double delta;
128 struct timeval tv;
129 do {
130 delta = t - RealTime::now();
131 if (delta <= 0.0)
132 return;
133 to_timeval(delta, &tv);
134 } while (select(0, NULL, NULL, NULL, &tv) < 0 && errno == EINTR);
135 # endif
136 #else
137 double delta = t - RealTime::now();
138 if (delta <= 0.0)
139 return;
140 while (rare(delta > 4294967.0)) {
141 xapian_sleep_milliseconds(4294967000u);
142 delta -= 4294967.0;
144 xapian_sleep_milliseconds(unsigned(delta * 1000.0));
145 #endif
150 #endif // XAPIAN_INCLUDED_REALTIME_H