[ci] Try to get .gitignore check to work
[xapian.git] / xapian-core / matcher / matchtimeout.h
blob21aa8f1e04f0f9e08d7c5032bb523cec33f8c857
1 /** @file matchtimeout.h
2 * @brief Time limits for the matcher
3 */
4 /* Copyright (C) 2013,2014,2015,2016,2017 Olly Betts
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.
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
19 * USA
22 #ifndef XAPIAN_INCLUDED_MATCHTIMEOUT_H
23 #define XAPIAN_INCLUDED_MATCHTIMEOUT_H
25 #ifdef HAVE_TIMER_CREATE
26 #include "realtime.h"
28 #include <signal.h>
29 #include <time.h>
30 #include "safeunistd.h" // For _POSIX_* feature test macros.
32 extern "C" {
34 static void
35 set_timeout_flag(union sigval sv)
37 *(reinterpret_cast<volatile bool*>(sv.sival_ptr)) = true;
42 // The monotonic clock is the better basis for timeouts, but not always
43 // available.
45 #ifndef _POSIX_MONOTONIC_CLOCK
46 const clockid_t TIMEOUT_CLOCK = CLOCK_REALTIME;
47 #elif defined __sun
48 // Solaris defines CLOCK_MONOTONIC, but "man timer_create" doesn't mention it
49 // and when using it timer_create() fails with "EPERM" (perhaps you need to be
50 // root to use it? I can't test that).
52 // Solaris defines _POSIX_MONOTONIC_CLOCK so we need to special case.
53 const clockid_t TIMEOUT_CLOCK = CLOCK_REALTIME;
54 #elif defined __CYGWIN__
55 // https://cygwin.com/cygwin-api/std-notes.html currently (2016-05-13) says:
57 // clock_nanosleep currently supports only CLOCK_REALTIME and
58 // CLOCK_MONOTONIC. clock_setres, clock_settime, and timer_create
59 // currently support only CLOCK_REALTIME.
61 // So CLOCK_MONOTONIC is defined, but not supported by timer_create().
62 const clockid_t TIMEOUT_CLOCK = CLOCK_REALTIME;
63 #else
64 const clockid_t TIMEOUT_CLOCK = CLOCK_MONOTONIC;
65 #endif
67 class TimeOut {
68 struct sigevent sev;
69 timer_t timerid;
70 volatile bool expired;
72 TimeOut(const TimeOut&) = delete;
74 TimeOut& operator=(const TimeOut&) = delete;
76 public:
77 explicit TimeOut(double limit) : expired(false) {
78 if (limit > 0) {
79 sev.sigev_notify = SIGEV_THREAD;
80 sev.sigev_notify_function = set_timeout_flag;
81 sev.sigev_notify_attributes = NULL;
82 sev.sigev_value.sival_ptr =
83 static_cast<void*>(const_cast<bool*>(&expired));
84 if (usual(timer_create(TIMEOUT_CLOCK, &sev, &timerid) == 0)) {
85 struct itimerspec interval;
86 interval.it_interval.tv_sec = 0;
87 interval.it_interval.tv_nsec = 0;
88 RealTime::to_timespec(limit, &interval.it_value);
89 if (usual(timer_settime(timerid, 0, &interval, NULL) == 0)) {
90 // Timeout successfully set.
91 return;
93 timer_delete(timerid);
96 sev.sigev_notify = SIGEV_NONE;
99 ~TimeOut() {
100 if (sev.sigev_notify != SIGEV_NONE) {
101 timer_delete(timerid);
102 sev.sigev_notify = SIGEV_NONE;
106 bool timed_out() const { return expired; }
108 #else
109 class TimeOut {
110 public:
111 explicit TimeOut(double) { }
112 bool timed_out() const { return false; }
114 #endif
116 #endif // XAPIAN_INCLUDED_MATCHTIMEOUT_H