]> code.delx.au - gnu-emacs/blob - src/blockinput.h
Simplify SIGIO usage.
[gnu-emacs] / src / blockinput.h
1 /* blockinput.h - interface to blocking complicated interrupt-driven input.
2 Copyright (C) 1989, 1993, 2001-2012 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs 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 3 of the License, or
9 (at your option) any later version.
10
11 GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
18
19 #ifndef EMACS_BLOCKINPUT_H
20 #define EMACS_BLOCKINPUT_H
21
22 #include "atimer.h"
23
24 /* When Emacs is using signal-driven input, the processing of those
25 input signals can get pretty hairy. For example, when Emacs is
26 running under X windows, handling an input signal can entail
27 retrieving events from the X event queue, or making other X calls.
28
29 If an input signal occurs while Emacs is in the midst of some
30 non-reentrant code, and the signal processing invokes that same
31 code, we lose. For example, malloc and the Xlib functions aren't
32 usually re-entrant, and both are used by the X input signal handler
33 - if we try to process an input signal in the midst of executing
34 any of these functions, we'll lose.
35
36 To avoid this, we make the following requirements:
37
38 * Everyone must evaluate BLOCK_INPUT before entering these functions,
39 and then call UNBLOCK_INPUT after performing them. Calls
40 BLOCK_INPUT and UNBLOCK_INPUT may be nested.
41
42 * Any complicated interrupt handling code should test
43 interrupt_input_blocked, and put off its work until later.
44
45 * If the interrupt handling code wishes, it may set
46 interrupt_input_pending to a non-zero value. If that flag is set
47 when input becomes unblocked, UNBLOCK_INPUT will send a new SIGIO. */
48
49 extern volatile int interrupt_input_blocked;
50
51 /* Nonzero means an input interrupt has arrived
52 during the current critical section. */
53 extern int interrupt_input_pending;
54
55
56 /* Non-zero means asynchronous timers should be run when input is
57 unblocked. */
58
59 extern int pending_atimers;
60
61
62 /* Begin critical section. */
63 #define BLOCK_INPUT (interrupt_input_blocked++)
64
65 /* End critical section.
66
67 If doing signal-driven input, and a signal came in when input was
68 blocked, reinvoke the signal handler now to deal with it.
69
70 Always test interrupt_input_pending; that's not too expensive, and
71 it'll never get set if we don't need to resignal. This is simpler
72 than dealing here with every configuration option that might affect
73 whether interrupt_input_pending can be nonzero. */
74
75 #define UNBLOCK_INPUT \
76 do \
77 { \
78 --interrupt_input_blocked; \
79 if (interrupt_input_blocked == 0) \
80 { \
81 if (interrupt_input_pending) \
82 reinvoke_input_signal (); \
83 if (pending_atimers) \
84 do_pending_atimers (); \
85 } \
86 else if (interrupt_input_blocked < 0) \
87 emacs_abort (); \
88 } \
89 while (0)
90
91 /* Undo any number of BLOCK_INPUT calls,
92 and also reinvoke any pending signal. */
93
94 #define TOTALLY_UNBLOCK_INPUT \
95 do if (interrupt_input_blocked != 0) \
96 { \
97 interrupt_input_blocked = 1; \
98 UNBLOCK_INPUT; \
99 } \
100 while (0)
101
102 /* Undo any number of BLOCK_INPUT calls down to level LEVEL,
103 and also (if the level is now 0) reinvoke any pending signal. */
104
105 #define UNBLOCK_INPUT_TO(LEVEL) \
106 do \
107 { \
108 interrupt_input_blocked = (LEVEL) + 1; \
109 UNBLOCK_INPUT; \
110 } \
111 while (0)
112
113 #define UNBLOCK_INPUT_RESIGNAL UNBLOCK_INPUT
114
115 /* In critical section ? */
116 #define INPUT_BLOCKED_P (interrupt_input_blocked > 0)
117
118 /* Defined in keyboard.c */
119 extern void reinvoke_input_signal (void);
120
121 #endif /* EMACS_BLOCKINPUT_H */