xapian-core  2.0.0
matchtimeout.h
Go to the documentation of this file.
1 
4 /* Copyright (C) 2013,2014,2015,2016,2017 Olly Betts
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (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, see
18  * <https://www.gnu.org/licenses/>.
19  */
20 
21 #ifndef XAPIAN_INCLUDED_MATCHTIMEOUT_H
22 #define XAPIAN_INCLUDED_MATCHTIMEOUT_H
23 
24 #ifndef PACKAGE
25 # error config.h must be included first in each C++ source file
26 #endif
27 
28 #ifdef HAVE_TIMER_CREATE
29 #include "realtime.h"
30 
31 #include <signal.h>
32 #include <time.h>
33 #include "safeunistd.h" // For _POSIX_* feature test macros.
34 
35 extern "C" {
36 
37 static void
38 set_timeout_flag(union sigval sv)
39 {
40  *(reinterpret_cast<volatile bool*>(sv.sival_ptr)) = true;
41 }
42 
43 }
44 
45 // The monotonic clock is the better basis for timeouts, but not always
46 // available.
47 
48 #ifndef _POSIX_MONOTONIC_CLOCK
49 const clockid_t TIMEOUT_CLOCK = CLOCK_REALTIME;
50 #elif defined __sun
51 // Solaris defines CLOCK_MONOTONIC, but "man timer_create" doesn't mention it
52 // and when using it timer_create() fails with "EPERM" (perhaps you need to be
53 // root to use it? I can't test that).
54 //
55 // Solaris defines _POSIX_MONOTONIC_CLOCK so we need to special case.
56 const clockid_t TIMEOUT_CLOCK = CLOCK_REALTIME;
57 #elif defined __CYGWIN__
58 // https://cygwin.com/cygwin-api/std-notes.html currently (2023-04-18) says:
59 //
60 // clock_nanosleep currently supports only CLOCK_REALTIME and
61 // CLOCK_MONOTONIC. clock_setres, clock_settime, and timer_create
62 // currently support only CLOCK_REALTIME.
63 //
64 // So CLOCK_MONOTONIC is defined, but not supported by timer_create().
65 const clockid_t TIMEOUT_CLOCK = CLOCK_REALTIME;
66 #else
67 const clockid_t TIMEOUT_CLOCK = CLOCK_MONOTONIC;
68 #endif
69 
70 class TimeOut {
71  struct sigevent sev;
72  timer_t timerid;
73  volatile bool expired = false;
74 
75  TimeOut(const TimeOut&) = delete;
76 
77  TimeOut& operator=(const TimeOut&) = delete;
78 
79  public:
80  explicit TimeOut(double limit) {
81  if (limit > 0) {
82  sev.sigev_notify = SIGEV_THREAD;
83  sev.sigev_notify_function = set_timeout_flag;
84  sev.sigev_notify_attributes = NULL;
85  sev.sigev_value.sival_ptr =
86  static_cast<void*>(const_cast<bool*>(&expired));
87  if (usual(timer_create(TIMEOUT_CLOCK, &sev, &timerid) == 0)) {
88  struct itimerspec interval;
89  interval.it_interval.tv_sec = 0;
90  interval.it_interval.tv_nsec = 0;
91  RealTime::to_timespec(limit, &interval.it_value);
92  if (usual(timer_settime(timerid, 0, &interval, NULL) == 0)) {
93  // Timeout successfully set.
94  return;
95  }
96  timer_delete(timerid);
97  }
98  }
99  sev.sigev_notify = SIGEV_NONE;
100  }
101 
102  ~TimeOut() {
103  if (sev.sigev_notify != SIGEV_NONE) {
104  timer_delete(timerid);
105  sev.sigev_notify = SIGEV_NONE;
106  }
107  }
108 
109  bool timed_out() const { return expired; }
110 };
111 #else
112 class TimeOut {
113  public:
114  explicit TimeOut(double) { }
115  bool timed_out() const { return false; }
116 };
117 #endif
118 
119 #endif // XAPIAN_INCLUDED_MATCHTIMEOUT_H
TimeOut(double)
Definition: matchtimeout.h:114
bool timed_out() const
Definition: matchtimeout.h:115
#define usual(COND)
Definition: config.h:608
Functions for handling a time or time interval in a double.
<unistd.h>, but with compat.