xapian-core  1.4.27
realtime.h
Go to the documentation of this file.
1 
4 /* Copyright (C) 2010,2011,2013,2014,2015,2020 Olly Betts
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #ifndef XAPIAN_INCLUDED_REALTIME_H
22 #define XAPIAN_INCLUDED_REALTIME_H
23 
24 #ifndef PACKAGE
25 # error config.h must be included first in each C++ source file
26 #endif
27 
28 #include <cerrno>
29 #include <cmath>
30 #include <ctime>
31 
32 #ifndef __WIN32__
33 # ifdef HAVE_FTIME
34 # include <sys/timeb.h>
35 # endif
36 # ifdef HAVE_GETTIMEOFDAY
37 # include <sys/time.h>
38 # endif
39 # include "safesysselect.h"
40 #else
41 # include <sys/types.h>
42 # include <sys/timeb.h>
43 extern void xapian_sleep_milliseconds(unsigned int millisecs);
44 #endif
45 
46 namespace RealTime {
47 
49 inline double now() {
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().
54  //
55  // (Also, POSIX.1-2008 stopped specifying ftime(), and marked gettimeofday()
56  // as obsolete, recommending clock_gettime() instead.)
57  //
58  // Modern mingw provides clock_gettime(). For older mingw and MSVC we fall
59  // back to _ftime64().
60  struct timespec ts;
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
66  struct timeval tv;
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
71  struct timeb tp;
72 # ifdef FTIME_RETURNS_VOID
73  ftime(&tp);
74 # else
75  if (rare(ftime(&tp) != 0))
76  return double(std::time(NULL));
77 # endif
78  return tp.time + (tp.millitm * 1e-3);
79 # else
80  return double(std::time(NULL));
81 # endif
82 #else
83  // For __WIN32__.
84  struct __timeb64 tp;
85  _ftime64(&tp);
86  return tp.time + tp.millitm * 1e-3;
87 #endif
88 }
89 
95 inline double end_time(double timeout) {
96  return (timeout == 0.0 ? timeout : timeout + now());
97 }
98 
99 #if defined HAVE_NANOSLEEP || defined HAVE_TIMER_CREATE
100 inline void to_timespec(double t, struct timespec *ts) {
102  double secs;
103  ts->tv_nsec = long(std::modf(t, &secs) * 1e9);
104  ts->tv_sec = long(secs);
105 }
106 #endif
107 
109 #ifndef __WIN32__
110 inline void to_timeval(double t, struct timeval *tv) {
111  double secs;
112  tv->tv_usec = long(std::modf(t, &secs) * 1e6);
113  tv->tv_sec = long(secs);
114 }
115 #else
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)
118 
119 inline void to_timeval_(double t, long & tv_sec, long & tv_usec) {
120  double secs;
121  tv_usec = long(std::modf(t, &secs) * 1e6);
122  tv_sec = long(secs);
123 }
124 #endif
125 
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();
131  if (delta <= 0.0)
132  return;
133  struct timespec ts;
134  to_timespec(delta, &ts);
135  while (nanosleep(&ts, &ts) < 0 && errno == EINTR) { }
136 #elif !defined __WIN32__
137  double delta;
138  struct timeval tv;
139  do {
140  delta = t - RealTime::now();
141  if (delta <= 0.0)
142  return;
143  to_timeval(delta, &tv);
144  } while (select(0, NULL, NULL, NULL, &tv) < 0 &&
145  (errno == EINTR || errno == EAGAIN));
146 #else
147  double delta = t - RealTime::now();
148  if (delta <= 0.0)
149  return;
150  while (rare(delta > 4294967.0)) {
151  xapian_sleep_milliseconds(4294967000u);
152  delta -= 4294967.0;
153  }
154  xapian_sleep_milliseconds(unsigned(delta * 1000.0));
155 #endif
156 }
157 
158 }
159 
160 #endif // XAPIAN_INCLUDED_REALTIME_H
include <sys/select.h> with portability workarounds.
unsigned timeout
A timeout value in milliseconds.
Definition: types.h:100
#define usual(COND)
Definition: config.h:576
void sleep(double t)
Sleep until the time represented by this object.
Definition: realtime.h:127
double end_time(double timeout)
Return the end time for a timeout in timeout seconds.
Definition: realtime.h:95
#define rare(COND)
Definition: config.h:575
double now()
Return the current time.
Definition: realtime.h:49
void to_timeval(double t, struct timeval *tv)
Fill in struct timeval from number of seconds in a double.
Definition: realtime.h:110