Commit | Line | Data |
---|---|---|
872870b2 | 1 | /* Function for handling the GLib event loop. |
114f9c96 | 2 | Copyright (C) 2009, 2010 |
872870b2 JD |
3 | Free Software Foundation, Inc. |
4 | ||
5 | This file is part of GNU Emacs. | |
6 | ||
7 | GNU Emacs is free software: you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation, either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | GNU Emacs is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "config.h" | |
21 | ||
22 | #if defined (USE_GTK) || defined (HAVE_GCONF) | |
23 | #include <glib.h> | |
24 | #include <errno.h> | |
25 | #include <setjmp.h> | |
26 | #include "xgselect.h" | |
27 | ||
28 | static GPollFD *gfds; | |
29 | static int gfds_size; | |
30 | ||
31 | int | |
32 | xg_select (max_fds, rfds, wfds, efds, timeout) | |
33 | int max_fds; | |
34 | SELECT_TYPE *rfds; | |
35 | SELECT_TYPE *wfds; | |
36 | SELECT_TYPE *efds; | |
37 | EMACS_TIME *timeout; | |
38 | { | |
39 | SELECT_TYPE all_rfds, all_wfds; | |
40 | EMACS_TIME tmo, *tmop = timeout; | |
41 | ||
42 | GMainContext *context = g_main_context_default (); | |
43 | int have_wfds = wfds != NULL; | |
44 | int n_gfds = 0, our_tmo = 0, retval = 0, our_fds = 0; | |
45 | int prio, i, nfds, tmo_in_millisec; | |
46 | ||
47 | if (rfds) memcpy (&all_rfds, rfds, sizeof (all_rfds)); | |
48 | else FD_ZERO (&all_rfds); | |
49 | if (wfds) memcpy (&all_wfds, wfds, sizeof (all_rfds)); | |
50 | else FD_ZERO (&all_wfds); | |
51 | ||
52 | /* Update event sources in GLib. */ | |
53 | g_main_context_pending (context); | |
54 | ||
55 | do { | |
56 | if (n_gfds > gfds_size) | |
57 | { | |
58 | while (n_gfds > gfds_size) | |
59 | gfds_size *= 2; | |
60 | xfree (gfds); | |
61 | gfds = xmalloc (sizeof (*gfds) * gfds_size); | |
62 | } | |
63 | ||
64 | n_gfds = g_main_context_query (context, | |
65 | G_PRIORITY_LOW, | |
66 | &tmo_in_millisec, | |
67 | gfds, | |
68 | gfds_size); | |
69 | } while (n_gfds > gfds_size); | |
70 | ||
71 | for (i = 0; i < n_gfds; ++i) | |
72 | { | |
73 | if (gfds[i].events & G_IO_IN) | |
74 | { | |
75 | FD_SET (gfds[i].fd, &all_rfds); | |
76 | if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; | |
77 | } | |
78 | if (gfds[i].events & G_IO_OUT) | |
79 | { | |
80 | FD_SET (gfds[i].fd, &all_wfds); | |
81 | if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; | |
82 | have_wfds = 1; | |
83 | } | |
84 | } | |
85 | ||
86 | if (tmo_in_millisec >= 0) | |
87 | { | |
88 | EMACS_SET_SECS_USECS (tmo, tmo_in_millisec/1000, | |
89 | 1000 * (tmo_in_millisec % 1000)); | |
90 | if (!timeout) our_tmo = 1; | |
91 | else | |
92 | { | |
93 | EMACS_TIME difference; | |
94 | ||
95 | EMACS_SUB_TIME (difference, tmo, *timeout); | |
96 | if (EMACS_TIME_NEG_P (difference)) our_tmo = 1; | |
97 | } | |
98 | ||
99 | if (our_tmo) tmop = &tmo; | |
100 | } | |
101 | ||
102 | nfds = select (max_fds+1, &all_rfds, have_wfds ? &all_wfds : NULL, | |
103 | efds, tmop); | |
104 | ||
105 | if (nfds < 0) | |
106 | retval = nfds; | |
107 | else if (nfds > 0) | |
108 | { | |
109 | for (i = 0; i < max_fds+1; ++i) | |
110 | { | |
111 | if (FD_ISSET (i, &all_rfds)) | |
112 | { | |
113 | if (rfds && FD_ISSET (i, rfds)) ++retval; | |
114 | else ++our_fds; | |
115 | } | |
116 | if (have_wfds && FD_ISSET (i, &all_wfds)) | |
117 | { | |
118 | if (wfds && FD_ISSET (i, wfds)) ++retval; | |
119 | else ++our_fds; | |
120 | } | |
121 | if (efds && FD_ISSET (i, efds)) | |
122 | ++retval; | |
123 | } | |
124 | } | |
125 | ||
126 | if (our_fds > 0 || (nfds == 0 && our_tmo)) | |
127 | { | |
128 | ||
129 | /* If Gtk+ is in use eventually gtk_main_iteration will be called, | |
130 | unless retval is zero. */ | |
131 | #ifdef USE_GTK | |
132 | if (retval == 0) | |
133 | #endif | |
134 | while (g_main_context_pending (context)) | |
135 | g_main_context_dispatch (context); | |
136 | ||
137 | /* To not have to recalculate timeout, return like this. */ | |
138 | if (retval == 0) | |
139 | { | |
140 | retval = -1; | |
141 | errno = EINTR; | |
142 | } | |
143 | } | |
144 | ||
145 | return retval; | |
146 | } | |
147 | #endif /* defined (USE_GTK) || defined (HAVE_GCONF) */ | |
148 | ||
149 | void | |
150 | xgselect_initialize () | |
151 | { | |
152 | #if defined (USE_GTK) || defined (HAVE_GCONF) | |
153 | gfds_size = 128; | |
154 | gfds = xmalloc (sizeof (*gfds)*gfds_size); | |
155 | #endif /* defined (USE_GTK) || defined (HAVE_GCONF) */ | |
156 | } | |
157 | ||
964f5b2b MB |
158 | /* arch-tag: c5873ee3-d1f6-44f9-9f3b-b14f70fd0e6a |
159 | (do not change this comment) */ |