/src/pango/subprojects/glib/gobject/gsourceclosure.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* GObject - GLib Type, Object, Parameter and Signal Library |
2 | | * Copyright (C) 2001 Red Hat, Inc. |
3 | | * |
4 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
5 | | * |
6 | | * This library is free software; you can redistribute it and/or |
7 | | * modify it under the terms of the GNU Lesser General Public |
8 | | * License as published by the Free Software Foundation; either |
9 | | * version 2.1 of the License, or (at your option) any later version. |
10 | | * |
11 | | * This library 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 GNU |
14 | | * Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General |
17 | | * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. |
18 | | */ |
19 | | |
20 | | #include "config.h" |
21 | | |
22 | | #include "gsourceclosure.h" |
23 | | #include "gboxed.h" |
24 | | #include "genums.h" |
25 | | #include "gmarshal.h" |
26 | | #include "gvalue.h" |
27 | | #include "gvaluetypes.h" |
28 | | #ifdef G_OS_UNIX |
29 | | #include "glib-unix.h" |
30 | | #endif |
31 | | |
32 | | G_DEFINE_BOXED_TYPE (GIOChannel, g_io_channel, g_io_channel_ref, g_io_channel_unref) |
33 | | |
34 | | GType |
35 | | g_io_condition_get_type (void) |
36 | 0 | { |
37 | 0 | static GType etype = 0; |
38 | |
|
39 | 0 | if (g_once_init_enter_pointer (&etype)) |
40 | 0 | { |
41 | 0 | static const GFlagsValue values[] = { |
42 | 0 | { G_IO_IN, "G_IO_IN", "in" }, |
43 | 0 | { G_IO_OUT, "G_IO_OUT", "out" }, |
44 | 0 | { G_IO_PRI, "G_IO_PRI", "pri" }, |
45 | 0 | { G_IO_ERR, "G_IO_ERR", "err" }, |
46 | 0 | { G_IO_HUP, "G_IO_HUP", "hup" }, |
47 | 0 | { G_IO_NVAL, "G_IO_NVAL", "nval" }, |
48 | 0 | { 0, NULL, NULL } |
49 | 0 | }; |
50 | 0 | GType type_id = g_flags_register_static ("GIOCondition", values); |
51 | 0 | g_once_init_leave_pointer (&etype, type_id); |
52 | 0 | } |
53 | 0 | return etype; |
54 | 0 | } |
55 | | |
56 | | /* We need to hand-write this marshaler, since it doesn't have an |
57 | | * instance object. |
58 | | */ |
59 | | static void |
60 | | source_closure_marshal_BOOLEAN__VOID (GClosure *closure, |
61 | | GValue *return_value, |
62 | | guint n_param_values, |
63 | | const GValue *param_values, |
64 | | gpointer invocation_hint, |
65 | | gpointer marshal_data) |
66 | 0 | { |
67 | 0 | GSourceFunc callback; |
68 | 0 | GCClosure *cc = (GCClosure*) closure; |
69 | 0 | gboolean v_return; |
70 | |
|
71 | 0 | g_return_if_fail (return_value != NULL); |
72 | 0 | g_return_if_fail (n_param_values == 0); |
73 | | |
74 | 0 | callback = (GSourceFunc) (marshal_data ? marshal_data : cc->callback); |
75 | |
|
76 | 0 | v_return = callback (closure->data); |
77 | |
|
78 | 0 | g_value_set_boolean (return_value, v_return); |
79 | 0 | } |
80 | | |
81 | | static gboolean |
82 | | io_watch_closure_callback (GIOChannel *channel, |
83 | | GIOCondition condition, |
84 | | gpointer data) |
85 | 0 | { |
86 | 0 | GClosure *closure = data; |
87 | |
|
88 | 0 | GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT }; |
89 | 0 | GValue result_value = G_VALUE_INIT; |
90 | 0 | gboolean result; |
91 | |
|
92 | 0 | g_value_init (&result_value, G_TYPE_BOOLEAN); |
93 | 0 | g_value_init (¶ms[0], G_TYPE_IO_CHANNEL); |
94 | 0 | g_value_set_boxed (¶ms[0], channel); |
95 | | |
96 | 0 | g_value_init (¶ms[1], G_TYPE_IO_CONDITION); |
97 | 0 | g_value_set_flags (¶ms[1], condition); |
98 | |
|
99 | 0 | g_closure_invoke (closure, &result_value, 2, params, NULL); |
100 | |
|
101 | 0 | result = g_value_get_boolean (&result_value); |
102 | 0 | g_value_unset (&result_value); |
103 | 0 | g_value_unset (¶ms[0]); |
104 | 0 | g_value_unset (¶ms[1]); |
105 | |
|
106 | 0 | return result; |
107 | 0 | } |
108 | | |
109 | | static gboolean |
110 | | g_child_watch_closure_callback (GPid pid, |
111 | | gint status, |
112 | | gpointer data) |
113 | 0 | { |
114 | 0 | GClosure *closure = data; |
115 | |
|
116 | 0 | GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT }; |
117 | 0 | GValue result_value = G_VALUE_INIT; |
118 | 0 | gboolean result; |
119 | |
|
120 | 0 | g_value_init (&result_value, G_TYPE_BOOLEAN); |
121 | |
|
122 | 0 | #ifdef G_OS_UNIX |
123 | 0 | g_value_init (¶ms[0], G_TYPE_ULONG); |
124 | 0 | G_STATIC_ASSERT (sizeof (pid) <= sizeof (unsigned long)); |
125 | 0 | g_value_set_ulong (¶ms[0], (gulong) pid); |
126 | 0 | #endif |
127 | | #ifdef G_OS_WIN32 |
128 | | g_value_init (¶ms[0], G_TYPE_POINTER); |
129 | | g_value_set_pointer (¶ms[0], pid); |
130 | | #endif |
131 | |
|
132 | 0 | g_value_init (¶ms[1], G_TYPE_INT); |
133 | 0 | g_value_set_int (¶ms[1], status); |
134 | |
|
135 | 0 | g_closure_invoke (closure, &result_value, 2, params, NULL); |
136 | |
|
137 | 0 | result = g_value_get_boolean (&result_value); |
138 | 0 | g_value_unset (&result_value); |
139 | 0 | g_value_unset (¶ms[0]); |
140 | 0 | g_value_unset (¶ms[1]); |
141 | |
|
142 | 0 | return result; |
143 | 0 | } |
144 | | |
145 | | #ifdef G_OS_UNIX |
146 | | static gboolean |
147 | | g_unix_fd_source_closure_callback (int fd, |
148 | | GIOCondition condition, |
149 | | gpointer data) |
150 | 0 | { |
151 | 0 | GClosure *closure = data; |
152 | |
|
153 | 0 | GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT }; |
154 | 0 | GValue result_value = G_VALUE_INIT; |
155 | 0 | gboolean result; |
156 | |
|
157 | 0 | g_value_init (&result_value, G_TYPE_BOOLEAN); |
158 | |
|
159 | 0 | g_value_init (¶ms[0], G_TYPE_INT); |
160 | 0 | g_value_set_int (¶ms[0], fd); |
161 | |
|
162 | 0 | g_value_init (¶ms[1], G_TYPE_IO_CONDITION); |
163 | 0 | g_value_set_flags (¶ms[1], condition); |
164 | |
|
165 | 0 | g_closure_invoke (closure, &result_value, 2, params, NULL); |
166 | |
|
167 | 0 | result = g_value_get_boolean (&result_value); |
168 | 0 | g_value_unset (&result_value); |
169 | 0 | g_value_unset (¶ms[0]); |
170 | 0 | g_value_unset (¶ms[1]); |
171 | |
|
172 | 0 | return result; |
173 | 0 | } |
174 | | #endif |
175 | | |
176 | | static gboolean |
177 | | source_closure_callback (gpointer data) |
178 | 0 | { |
179 | 0 | GClosure *closure = data; |
180 | 0 | GValue result_value = G_VALUE_INIT; |
181 | 0 | gboolean result; |
182 | |
|
183 | 0 | g_value_init (&result_value, G_TYPE_BOOLEAN); |
184 | | |
185 | 0 | g_closure_invoke (closure, &result_value, 0, NULL, NULL); |
186 | |
|
187 | 0 | result = g_value_get_boolean (&result_value); |
188 | 0 | g_value_unset (&result_value); |
189 | |
|
190 | 0 | return result; |
191 | 0 | } |
192 | | |
193 | | static void |
194 | | closure_callback_get (gpointer cb_data, |
195 | | GSource *source, |
196 | | GSourceFunc *func, |
197 | | gpointer *data) |
198 | 0 | { |
199 | 0 | GSourceFunc closure_callback = source->source_funcs->closure_callback; |
200 | |
|
201 | 0 | if (!closure_callback) |
202 | 0 | { |
203 | 0 | if (source->source_funcs == &g_io_watch_funcs) |
204 | 0 | closure_callback = (GSourceFunc)io_watch_closure_callback; |
205 | 0 | else if (source->source_funcs == &g_child_watch_funcs) |
206 | 0 | closure_callback = (GSourceFunc)g_child_watch_closure_callback; |
207 | 0 | #ifdef G_OS_UNIX |
208 | 0 | else if (source->source_funcs == &g_unix_fd_source_funcs) |
209 | 0 | closure_callback = (GSourceFunc)g_unix_fd_source_closure_callback; |
210 | 0 | #endif |
211 | 0 | else if (source->source_funcs == &g_timeout_funcs || |
212 | 0 | #ifdef G_OS_UNIX |
213 | 0 | source->source_funcs == &g_unix_signal_funcs || |
214 | 0 | #endif |
215 | 0 | source->source_funcs == &g_idle_funcs) |
216 | 0 | closure_callback = source_closure_callback; |
217 | 0 | } |
218 | |
|
219 | 0 | *func = closure_callback; |
220 | 0 | *data = cb_data; |
221 | 0 | } |
222 | | |
223 | | static GSourceCallbackFuncs closure_callback_funcs = { |
224 | | (void (*) (gpointer)) g_closure_ref, |
225 | | (void (*) (gpointer)) g_closure_unref, |
226 | | closure_callback_get |
227 | | }; |
228 | | |
229 | | static void |
230 | | closure_invalidated (gpointer user_data, |
231 | | GClosure *closure) |
232 | 0 | { |
233 | 0 | g_source_destroy (user_data); |
234 | 0 | } |
235 | | |
236 | | /** |
237 | | * g_source_set_closure: |
238 | | * @source: the source |
239 | | * @closure: a #GClosure |
240 | | * |
241 | | * Set the callback for a source as a #GClosure. |
242 | | * |
243 | | * If the source is not one of the standard GLib types, the @closure_callback |
244 | | * and @closure_marshal fields of the #GSourceFuncs structure must have been |
245 | | * filled in with pointers to appropriate functions. |
246 | | */ |
247 | | void |
248 | | g_source_set_closure (GSource *source, |
249 | | GClosure *closure) |
250 | 0 | { |
251 | 0 | g_return_if_fail (source != NULL); |
252 | 0 | g_return_if_fail (closure != NULL); |
253 | | |
254 | 0 | if (!source->source_funcs->closure_callback && |
255 | 0 | #ifdef G_OS_UNIX |
256 | 0 | source->source_funcs != &g_unix_fd_source_funcs && |
257 | 0 | source->source_funcs != &g_unix_signal_funcs && |
258 | 0 | #endif |
259 | 0 | source->source_funcs != &g_child_watch_funcs && |
260 | 0 | source->source_funcs != &g_io_watch_funcs && |
261 | 0 | source->source_funcs != &g_timeout_funcs && |
262 | 0 | source->source_funcs != &g_idle_funcs) |
263 | 0 | { |
264 | 0 | g_critical (G_STRLOC ": closure cannot be set on GSource without GSourceFuncs::closure_callback"); |
265 | 0 | return; |
266 | 0 | } |
267 | | |
268 | 0 | g_closure_ref (closure); |
269 | 0 | g_closure_sink (closure); |
270 | 0 | g_source_set_callback_indirect (source, closure, &closure_callback_funcs); |
271 | |
|
272 | 0 | g_closure_add_invalidate_notifier (closure, source, closure_invalidated); |
273 | |
|
274 | 0 | if (G_CLOSURE_NEEDS_MARSHAL (closure)) |
275 | 0 | { |
276 | 0 | GClosureMarshal marshal = (GClosureMarshal)source->source_funcs->closure_marshal; |
277 | 0 | if (marshal) |
278 | 0 | g_closure_set_marshal (closure, marshal); |
279 | 0 | else if (source->source_funcs == &g_idle_funcs || |
280 | 0 | #ifdef G_OS_UNIX |
281 | 0 | source->source_funcs == &g_unix_signal_funcs || |
282 | 0 | #endif |
283 | 0 | source->source_funcs == &g_timeout_funcs) |
284 | 0 | g_closure_set_marshal (closure, source_closure_marshal_BOOLEAN__VOID); |
285 | 0 | else |
286 | 0 | g_closure_set_marshal (closure, g_cclosure_marshal_generic); |
287 | 0 | } |
288 | 0 | } |
289 | | |
290 | | static void |
291 | | dummy_closure_marshal (GClosure *closure, |
292 | | GValue *return_value, |
293 | | guint n_param_values, |
294 | | const GValue *param_values, |
295 | | gpointer invocation_hint, |
296 | | gpointer marshal_data) |
297 | 0 | { |
298 | 0 | if (G_VALUE_HOLDS_BOOLEAN (return_value)) |
299 | 0 | g_value_set_boolean (return_value, TRUE); |
300 | 0 | } |
301 | | |
302 | | /** |
303 | | * g_source_set_dummy_callback: |
304 | | * @source: the source |
305 | | * |
306 | | * Sets a dummy callback for @source. The callback will do nothing, and |
307 | | * if the source expects a #gboolean return value, it will return %TRUE. |
308 | | * (If the source expects any other type of return value, it will return |
309 | | * a 0/%NULL value; whatever g_value_init() initializes a #GValue to for |
310 | | * that type.) |
311 | | * |
312 | | * If the source is not one of the standard GLib types, the |
313 | | * @closure_callback and @closure_marshal fields of the #GSourceFuncs |
314 | | * structure must have been filled in with pointers to appropriate |
315 | | * functions. |
316 | | */ |
317 | | void |
318 | | g_source_set_dummy_callback (GSource *source) |
319 | 0 | { |
320 | 0 | GClosure *closure; |
321 | |
|
322 | 0 | closure = g_closure_new_simple (sizeof (GClosure), NULL); |
323 | 0 | g_closure_set_meta_marshal (closure, NULL, dummy_closure_marshal); |
324 | 0 | g_source_set_closure (source, closure); |
325 | 0 | } |