Branch data Line data Source code
1 : : /* GObject - GLib Type, Object, Parameter and Signal Library
2 : : * Copyright (C) 2000-2001 Red Hat, Inc.
3 : : * Copyright (C) 2005 Imendio AB
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library 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 GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : */
20 : :
21 : : /*
22 : : * MT safe with regards to reference counting.
23 : : */
24 : :
25 : : #include "config.h"
26 : :
27 : : #include "../glib/gvalgrind.h"
28 : : #include <string.h>
29 : :
30 : : #include <ffi.h>
31 : :
32 : : #include "gclosure.h"
33 : : #include "gboxed.h"
34 : : #include "gobject.h"
35 : : #include "genums.h"
36 : : #include "gvalue.h"
37 : : #include "gvaluetypes.h"
38 : : #include "gtype-private.h"
39 : :
40 : :
41 : : /**
42 : : * GClosure:
43 : : * @in_marshal: Indicates whether the closure is currently being invoked with
44 : : * g_closure_invoke()
45 : : * @is_invalid: Indicates whether the closure has been invalidated by
46 : : * g_closure_invalidate()
47 : : *
48 : : * A `GClosure` represents a callback supplied by the programmer.
49 : : *
50 : : * It will generally comprise a function of some kind and a marshaller
51 : : * used to call it. It is the responsibility of the marshaller to
52 : : * convert the arguments for the invocation from #GValues into
53 : : * a suitable form, perform the callback on the converted arguments,
54 : : * and transform the return value back into a #GValue.
55 : : *
56 : : * In the case of C programs, a closure usually just holds a pointer
57 : : * to a function and maybe a data argument, and the marshaller
58 : : * converts between #GValue and native C types. The GObject
59 : : * library provides the #GCClosure type for this purpose. Bindings for
60 : : * other languages need marshallers which convert between #GValues
61 : : * and suitable representations in the runtime of the language in
62 : : * order to use functions written in that language as callbacks. Use
63 : : * g_closure_set_marshal() to set the marshaller on such a custom
64 : : * closure implementation.
65 : : *
66 : : * Within GObject, closures play an important role in the
67 : : * implementation of signals. When a signal is registered, the
68 : : * @c_marshaller argument to g_signal_new() specifies the default C
69 : : * marshaller for any closure which is connected to this
70 : : * signal. GObject provides a number of C marshallers for this
71 : : * purpose, see the g_cclosure_marshal_*() functions. Additional C
72 : : * marshallers can be generated with the [glib-genmarshal][glib-genmarshal]
73 : : * utility. Closures can be explicitly connected to signals with
74 : : * g_signal_connect_closure(), but it usually more convenient to let
75 : : * GObject create a closure automatically by using one of the
76 : : * g_signal_connect_*() functions which take a callback function/user
77 : : * data pair.
78 : : *
79 : : * Using closures has a number of important advantages over a simple
80 : : * callback function/data pointer combination:
81 : : *
82 : : * - Closures allow the callee to get the types of the callback parameters,
83 : : * which means that language bindings don't have to write individual glue
84 : : * for each callback type.
85 : : *
86 : : * - The reference counting of #GClosure makes it easy to handle reentrancy
87 : : * right; if a callback is removed while it is being invoked, the closure
88 : : * and its parameters won't be freed until the invocation finishes.
89 : : *
90 : : * - g_closure_invalidate() and invalidation notifiers allow callbacks to be
91 : : * automatically removed when the objects they point to go away.
92 : : */
93 : :
94 : : #define CLOSURE_MAX_REF_COUNT ((1 << 15) - 1)
95 : : #define CLOSURE_MAX_N_GUARDS ((1 << 1) - 1)
96 : : #define CLOSURE_MAX_N_FNOTIFIERS ((1 << 2) - 1)
97 : : #define CLOSURE_MAX_N_INOTIFIERS ((1 << 8) - 1)
98 : : #define CLOSURE_N_MFUNCS(cl) (((cl)->n_guards << 1L))
99 : : /* same as G_CLOSURE_N_NOTIFIERS() (keep in sync) */
100 : : #define CLOSURE_N_NOTIFIERS(cl) (CLOSURE_N_MFUNCS (cl) + \
101 : : (cl)->n_fnotifiers + \
102 : : (cl)->n_inotifiers)
103 : :
104 : : typedef union {
105 : : GClosure closure;
106 : : gint vint;
107 : : } ClosureInt;
108 : :
109 : : #define CHANGE_FIELD(_closure, _field, _OP, _value, _must_set, _SET_OLD, _SET_NEW) \
110 : : G_STMT_START { \
111 : : ClosureInt *cunion = (ClosureInt*) _closure; \
112 : : gint new_int, old_int, success; \
113 : : do \
114 : : { \
115 : : ClosureInt tmp; \
116 : : tmp.vint = old_int = cunion->vint; \
117 : : _SET_OLD tmp.closure._field; \
118 : : tmp.closure._field _OP _value; \
119 : : _SET_NEW tmp.closure._field; \
120 : : new_int = tmp.vint; \
121 : : success = g_atomic_int_compare_and_exchange (&cunion->vint, old_int, new_int); \
122 : : } \
123 : : while (!success && _must_set); \
124 : : } G_STMT_END
125 : :
126 : : #define SWAP(_closure, _field, _value, _oldv) CHANGE_FIELD (_closure, _field, =, _value, TRUE, *(_oldv) =, (void) )
127 : : #define SET(_closure, _field, _value) CHANGE_FIELD (_closure, _field, =, _value, TRUE, (void), (void) )
128 : : #define INC(_closure, _field) CHANGE_FIELD (_closure, _field, +=, 1, TRUE, (void), (void) )
129 : : #define INC_ASSIGN(_closure, _field, _newv) CHANGE_FIELD (_closure, _field, +=, 1, TRUE, (void), *(_newv) = )
130 : : #define DEC(_closure, _field) CHANGE_FIELD (_closure, _field, -=, 1, TRUE, (void), (void) )
131 : : #define DEC_ASSIGN(_closure, _field, _newv) CHANGE_FIELD (_closure, _field, -=, 1, TRUE, (void), *(_newv) = )
132 : :
133 : : #if 0 /* for non-thread-safe closures */
134 : : #define SWAP(cl,f,v,o) (void) (*(o) = cl->f, cl->f = v)
135 : : #define SET(cl,f,v) (void) (cl->f = v)
136 : : #define INC(cl,f) (void) (cl->f += 1)
137 : : #define INC_ASSIGN(cl,f,n) (void) (cl->f += 1, *(n) = cl->f)
138 : : #define DEC(cl,f) (void) (cl->f -= 1)
139 : : #define DEC_ASSIGN(cl,f,n) (void) (cl->f -= 1, *(n) = cl->f)
140 : : #endif
141 : :
142 : : enum {
143 : : FNOTIFY,
144 : : INOTIFY,
145 : : PRE_NOTIFY,
146 : : POST_NOTIFY
147 : : };
148 : :
149 : :
150 : : /* --- functions --- */
151 : : /**
152 : : * g_closure_new_simple:
153 : : * @sizeof_closure: the size of the structure to allocate, must be at least
154 : : * `sizeof (GClosure)`
155 : : * @data: data to store in the @data field of the newly allocated #GClosure
156 : : *
157 : : * Allocates a struct of the given size and initializes the initial
158 : : * part as a #GClosure.
159 : : *
160 : : * This function is mainly useful when implementing new types of closures:
161 : : *
162 : : * |[<!-- language="C" -->
163 : : * typedef struct _MyClosure MyClosure;
164 : : * struct _MyClosure
165 : : * {
166 : : * GClosure closure;
167 : : * // extra data goes here
168 : : * };
169 : : *
170 : : * static void
171 : : * my_closure_finalize (gpointer notify_data,
172 : : * GClosure *closure)
173 : : * {
174 : : * MyClosure *my_closure = (MyClosure *)closure;
175 : : *
176 : : * // free extra data here
177 : : * }
178 : : *
179 : : * MyClosure *my_closure_new (gpointer data)
180 : : * {
181 : : * GClosure *closure;
182 : : * MyClosure *my_closure;
183 : : *
184 : : * closure = g_closure_new_simple (sizeof (MyClosure), data);
185 : : * my_closure = (MyClosure *) closure;
186 : : *
187 : : * // initialize extra data here
188 : : *
189 : : * g_closure_add_finalize_notifier (closure, notify_data,
190 : : * my_closure_finalize);
191 : : * return my_closure;
192 : : * }
193 : : * ]|
194 : : *
195 : : * Returns: (transfer floating): a floating reference to a new #GClosure
196 : : */
197 : : GClosure*
198 : 541611 : g_closure_new_simple (guint sizeof_closure,
199 : : gpointer data)
200 : : {
201 : : GClosure *closure;
202 : : gint private_size;
203 : : gchar *allocated;
204 : :
205 : 541611 : g_return_val_if_fail (sizeof_closure >= sizeof (GClosure), NULL);
206 : :
207 : 541611 : private_size = sizeof (GRealClosure) - sizeof (GClosure);
208 : :
209 : : #ifdef ENABLE_VALGRIND
210 : : /* See comments in gtype.c about what's going on here... */
211 [ - + ]: 541611 : if (RUNNING_ON_VALGRIND)
212 : : {
213 : 0 : private_size += sizeof (gpointer);
214 : :
215 : 0 : allocated = g_malloc0 (private_size + sizeof_closure + sizeof (gpointer));
216 : :
217 : 0 : *(gpointer *) (allocated + private_size + sizeof_closure) = allocated + sizeof (gpointer);
218 : :
219 : 0 : VALGRIND_MALLOCLIKE_BLOCK (allocated + private_size, sizeof_closure + sizeof (gpointer), 0, TRUE);
220 : 0 : VALGRIND_MALLOCLIKE_BLOCK (allocated + sizeof (gpointer), private_size - sizeof (gpointer), 0, TRUE);
221 : : }
222 : : else
223 : : #endif
224 : 541611 : allocated = g_malloc0 (private_size + sizeof_closure);
225 : :
226 : 541611 : closure = (GClosure *) (allocated + private_size);
227 : :
228 [ - + ]: 541611 : SET (closure, ref_count, 1);
229 [ - + ]: 541611 : SET (closure, floating, TRUE);
230 : 541611 : closure->data = data;
231 : :
232 : 541611 : return closure;
233 : : }
234 : :
235 : : static inline void
236 : 42535166 : closure_invoke_notifiers (GClosure *closure,
237 : : guint notify_type)
238 : : {
239 : : /* notifier layout:
240 : : * n_guards n_guards n_fnotif. n_inotifiers
241 : : * ->[[pre_guards][post_guards][fnotifiers][inotifiers]]
242 : : *
243 : : * CLOSURE_N_MFUNCS(cl) = n_guards + n_guards;
244 : : * CLOSURE_N_NOTIFIERS(cl) = CLOSURE_N_MFUNCS(cl) + n_fnotifiers + n_inotifiers
245 : : *
246 : : * constrains/catches:
247 : : * - closure->notifiers may be reloacted during callback
248 : : * - closure->n_fnotifiers and closure->n_inotifiers may change during callback
249 : : * - i.e. callbacks can be removed/added during invocation
250 : : * - must prepare for callback removal during FNOTIFY and INOTIFY (done via ->marshal= & ->data=)
251 : : * - must distinguish (->marshal= & ->data=) for INOTIFY vs. FNOTIFY (via ->in_inotify)
252 : : * + closure->n_guards is const during PRE_NOTIFY & POST_NOTIFY
253 : : * + none of the callbacks can cause recursion
254 : : * + closure->n_inotifiers is const 0 during FNOTIFY
255 : : */
256 [ + + + + : 42535166 : switch (notify_type)
# ]
257 : : {
258 : : GClosureNotifyData *ndata;
259 : : guint i, offs;
260 : 539472 : case FNOTIFY:
261 [ + + ]: 541441 : while (closure->n_fnotifiers)
262 : : {
263 : : guint n;
264 [ - + ]: 1969 : DEC_ASSIGN (closure, n_fnotifiers, &n);
265 : :
266 : 1969 : ndata = closure->notifiers + CLOSURE_N_MFUNCS (closure) + n;
267 : 1969 : closure->marshal = (GClosureMarshal) ndata->notify;
268 : 1969 : closure->data = ndata->data;
269 : 1969 : ndata->notify (ndata->data, closure);
270 : : }
271 : 539472 : closure->marshal = NULL;
272 : 539472 : closure->data = NULL;
273 : 539472 : break;
274 : 539440 : case INOTIFY:
275 [ - + ]: 539440 : SET (closure, in_inotify, TRUE);
276 [ + + ]: 558143 : while (closure->n_inotifiers)
277 : : {
278 : : guint n;
279 [ - + ]: 18703 : DEC_ASSIGN (closure, n_inotifiers, &n);
280 : :
281 : 18703 : ndata = closure->notifiers + CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers + n;
282 : 18703 : closure->marshal = (GClosureMarshal) ndata->notify;
283 : 18703 : closure->data = ndata->data;
284 : 18703 : ndata->notify (ndata->data, closure);
285 : : }
286 : 539440 : closure->marshal = NULL;
287 : 539440 : closure->data = NULL;
288 [ - + ]: 539440 : SET (closure, in_inotify, FALSE);
289 : 539440 : break;
290 : 20729576 : case PRE_NOTIFY:
291 : 20729576 : i = closure->n_guards;
292 : 20729576 : offs = 0;
293 [ + + ]: 20729505 : while (i--)
294 : : {
295 : 39 : ndata = closure->notifiers + offs + i;
296 : 39 : ndata->notify (ndata->data, closure);
297 : : }
298 : 20729466 : break;
299 : 20729177 : case POST_NOTIFY:
300 : 20729177 : i = closure->n_guards;
301 : 20729177 : offs = i;
302 [ + + ]: 20729170 : while (i--)
303 : : {
304 : 39 : ndata = closure->notifiers + offs + i;
305 : 39 : ndata->notify (ndata->data, closure);
306 : : }
307 : 20729131 : break;
308 : : }
309 : 42535010 : }
310 : :
311 : : static void
312 : 1632 : g_closure_set_meta_va_marshal (GClosure *closure,
313 : : GVaClosureMarshal va_meta_marshal)
314 : : {
315 : : GRealClosure *real_closure;
316 : :
317 : 1632 : g_return_if_fail (closure != NULL);
318 : 1632 : g_return_if_fail (va_meta_marshal != NULL);
319 : 1632 : g_return_if_fail (closure->is_invalid == FALSE);
320 : 1632 : g_return_if_fail (closure->in_marshal == FALSE);
321 : :
322 : 1632 : real_closure = G_REAL_CLOSURE (closure);
323 : :
324 : 1632 : g_return_if_fail (real_closure->meta_marshal != NULL);
325 : :
326 : 1632 : real_closure->va_meta_marshal = va_meta_marshal;
327 : : }
328 : :
329 : : /**
330 : : * g_closure_set_meta_marshal: (skip)
331 : : * @closure: a #GClosure
332 : : * @marshal_data: (closure meta_marshal): context-dependent data to pass
333 : : * to @meta_marshal
334 : : * @meta_marshal: a #GClosureMarshal function
335 : : *
336 : : * Sets the meta marshaller of @closure.
337 : : *
338 : : * A meta marshaller wraps the @closure's marshal and modifies the way
339 : : * it is called in some fashion. The most common use of this facility
340 : : * is for C callbacks.
341 : : *
342 : : * The same marshallers (generated by [glib-genmarshal][glib-genmarshal]),
343 : : * are used everywhere, but the way that we get the callback function
344 : : * differs. In most cases we want to use the @closure's callback, but in
345 : : * other cases we want to use some different technique to retrieve the
346 : : * callback function.
347 : : *
348 : : * For example, class closures for signals (see
349 : : * g_signal_type_cclosure_new()) retrieve the callback function from a
350 : : * fixed offset in the class structure. The meta marshaller retrieves
351 : : * the right callback and passes it to the marshaller as the
352 : : * @marshal_data argument.
353 : : */
354 : : void
355 : 20332 : g_closure_set_meta_marshal (GClosure *closure,
356 : : gpointer marshal_data,
357 : : GClosureMarshal meta_marshal)
358 : : {
359 : : GRealClosure *real_closure;
360 : :
361 : 20332 : g_return_if_fail (closure != NULL);
362 : 20332 : g_return_if_fail (meta_marshal != NULL);
363 : 20332 : g_return_if_fail (closure->is_invalid == FALSE);
364 : 20332 : g_return_if_fail (closure->in_marshal == FALSE);
365 : :
366 : 20332 : real_closure = G_REAL_CLOSURE (closure);
367 : :
368 : 20332 : g_return_if_fail (real_closure->meta_marshal == NULL);
369 : :
370 : 20332 : real_closure->meta_marshal = meta_marshal;
371 : 20332 : real_closure->meta_marshal_data = marshal_data;
372 : : }
373 : :
374 : : /**
375 : : * g_closure_add_marshal_guards: (skip)
376 : : * @closure: a #GClosure
377 : : * @pre_marshal_data: (closure pre_marshal_notify): data to pass
378 : : * to @pre_marshal_notify
379 : : * @pre_marshal_notify: a function to call before the closure callback
380 : : * @post_marshal_data: (closure post_marshal_notify): data to pass
381 : : * to @post_marshal_notify
382 : : * @post_marshal_notify: a function to call after the closure callback
383 : : *
384 : : * Adds a pair of notifiers which get invoked before and after the
385 : : * closure callback, respectively.
386 : : *
387 : : * This is typically used to protect the extra arguments for the
388 : : * duration of the callback. See g_object_watch_closure() for an
389 : : * example of marshal guards.
390 : : */
391 : : void
392 : 60 : g_closure_add_marshal_guards (GClosure *closure,
393 : : gpointer pre_marshal_data,
394 : : GClosureNotify pre_marshal_notify,
395 : : gpointer post_marshal_data,
396 : : GClosureNotify post_marshal_notify)
397 : : {
398 : : guint i;
399 : :
400 : 60 : g_return_if_fail (closure != NULL);
401 : 60 : g_return_if_fail (pre_marshal_notify != NULL);
402 : 60 : g_return_if_fail (post_marshal_notify != NULL);
403 : 60 : g_return_if_fail (closure->is_invalid == FALSE);
404 : 60 : g_return_if_fail (closure->in_marshal == FALSE);
405 : 60 : g_return_if_fail (closure->n_guards < CLOSURE_MAX_N_GUARDS);
406 : :
407 : 60 : closure->notifiers = g_renew (GClosureNotifyData, closure->notifiers, CLOSURE_N_NOTIFIERS (closure) + 2);
408 [ + - ]: 60 : if (closure->n_inotifiers)
409 : 60 : closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
410 : 60 : closure->n_fnotifiers +
411 : 60 : closure->n_inotifiers + 1)] = closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
412 : 60 : closure->n_fnotifiers + 0)];
413 [ - + ]: 60 : if (closure->n_inotifiers > 1)
414 : 0 : closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
415 : 0 : closure->n_fnotifiers +
416 : 0 : closure->n_inotifiers)] = closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
417 : 0 : closure->n_fnotifiers + 1)];
418 [ - + ]: 60 : if (closure->n_fnotifiers)
419 : 0 : closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
420 : 0 : closure->n_fnotifiers + 1)] = closure->notifiers[CLOSURE_N_MFUNCS (closure) + 0];
421 [ - + ]: 60 : if (closure->n_fnotifiers > 1)
422 : 0 : closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
423 : 0 : closure->n_fnotifiers)] = closure->notifiers[CLOSURE_N_MFUNCS (closure) + 1];
424 [ - + ]: 60 : if (closure->n_guards)
425 : 0 : closure->notifiers[(closure->n_guards +
426 : 0 : closure->n_guards + 1)] = closure->notifiers[closure->n_guards];
427 : 60 : i = closure->n_guards;
428 : 60 : closure->notifiers[i].data = pre_marshal_data;
429 : 60 : closure->notifiers[i].notify = pre_marshal_notify;
430 : 60 : closure->notifiers[i + 1].data = post_marshal_data;
431 : 60 : closure->notifiers[i + 1].notify = post_marshal_notify;
432 [ - + ]: 60 : INC (closure, n_guards);
433 : : }
434 : :
435 : : /**
436 : : * g_closure_add_finalize_notifier: (skip)
437 : : * @closure: a #GClosure
438 : : * @notify_data: (closure notify_func): data to pass to @notify_func
439 : : * @notify_func: the callback function to register
440 : : *
441 : : * Registers a finalization notifier which will be called when the
442 : : * reference count of @closure goes down to 0.
443 : : *
444 : : * Multiple finalization notifiers on a single closure are invoked in
445 : : * unspecified order. If a single call to g_closure_unref() results in
446 : : * the closure being both invalidated and finalized, then the invalidate
447 : : * notifiers will be run before the finalize notifiers.
448 : : */
449 : : void
450 : 2167 : g_closure_add_finalize_notifier (GClosure *closure,
451 : : gpointer notify_data,
452 : : GClosureNotify notify_func)
453 : : {
454 : : guint i;
455 : :
456 : 2167 : g_return_if_fail (closure != NULL);
457 : 2167 : g_return_if_fail (notify_func != NULL);
458 : 2167 : g_return_if_fail (closure->n_fnotifiers < CLOSURE_MAX_N_FNOTIFIERS);
459 : :
460 : 2167 : closure->notifiers = g_renew (GClosureNotifyData, closure->notifiers, CLOSURE_N_NOTIFIERS (closure) + 1);
461 [ - + ]: 2167 : if (closure->n_inotifiers)
462 : 0 : closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
463 : 0 : closure->n_fnotifiers +
464 : 0 : closure->n_inotifiers)] = closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
465 : 0 : closure->n_fnotifiers + 0)];
466 : 2167 : i = CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers;
467 : 2167 : closure->notifiers[i].data = notify_data;
468 : 2167 : closure->notifiers[i].notify = notify_func;
469 [ - + ]: 2167 : INC (closure, n_fnotifiers);
470 : : }
471 : :
472 : : /**
473 : : * g_closure_add_invalidate_notifier: (skip)
474 : : * @closure: a #GClosure
475 : : * @notify_data: (closure notify_func): data to pass to @notify_func
476 : : * @notify_func: the callback function to register
477 : : *
478 : : * Registers an invalidation notifier which will be called when the
479 : : * @closure is invalidated with g_closure_invalidate().
480 : : *
481 : : * Invalidation notifiers are invoked before finalization notifiers,
482 : : * in an unspecified order.
483 : : */
484 : : void
485 : 19162 : g_closure_add_invalidate_notifier (GClosure *closure,
486 : : gpointer notify_data,
487 : : GClosureNotify notify_func)
488 : : {
489 : : guint i;
490 : :
491 : 19162 : g_return_if_fail (closure != NULL);
492 : 19162 : g_return_if_fail (notify_func != NULL);
493 : 19162 : g_return_if_fail (closure->is_invalid == FALSE);
494 : 19162 : g_return_if_fail (closure->n_inotifiers < CLOSURE_MAX_N_INOTIFIERS);
495 : :
496 : 19162 : closure->notifiers = g_renew (GClosureNotifyData, closure->notifiers, CLOSURE_N_NOTIFIERS (closure) + 1);
497 : 19162 : i = CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers + closure->n_inotifiers;
498 : 19162 : closure->notifiers[i].data = notify_data;
499 : 19162 : closure->notifiers[i].notify = notify_func;
500 [ - + ]: 19162 : INC (closure, n_inotifiers);
501 : : }
502 : :
503 : : static inline gboolean
504 : 396 : closure_try_remove_inotify (GClosure *closure,
505 : : gpointer notify_data,
506 : : GClosureNotify notify_func)
507 : : {
508 : : GClosureNotifyData *ndata, *nlast;
509 : :
510 : 396 : nlast = closure->notifiers + CLOSURE_N_NOTIFIERS (closure) - 1;
511 [ + - ]: 401 : for (ndata = nlast + 1 - closure->n_inotifiers; ndata <= nlast; ndata++)
512 [ + + + - ]: 401 : if (ndata->notify == notify_func && ndata->data == notify_data)
513 : : {
514 [ - + ]: 396 : DEC (closure, n_inotifiers);
515 [ + + ]: 396 : if (ndata < nlast)
516 : 58 : *ndata = *nlast;
517 : :
518 : 396 : return TRUE;
519 : : }
520 : 0 : return FALSE;
521 : : }
522 : :
523 : : static inline gboolean
524 : 0 : closure_try_remove_fnotify (GClosure *closure,
525 : : gpointer notify_data,
526 : : GClosureNotify notify_func)
527 : : {
528 : : GClosureNotifyData *ndata, *nlast;
529 : :
530 : 0 : nlast = closure->notifiers + CLOSURE_N_NOTIFIERS (closure) - closure->n_inotifiers - 1;
531 [ # # ]: 0 : for (ndata = nlast + 1 - closure->n_fnotifiers; ndata <= nlast; ndata++)
532 [ # # # # ]: 0 : if (ndata->notify == notify_func && ndata->data == notify_data)
533 : : {
534 [ # # ]: 0 : DEC (closure, n_fnotifiers);
535 [ # # ]: 0 : if (ndata < nlast)
536 : 0 : *ndata = *nlast;
537 [ # # ]: 0 : if (closure->n_inotifiers)
538 : 0 : closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
539 : 0 : closure->n_fnotifiers)] = closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
540 : 0 : closure->n_fnotifiers +
541 : 0 : closure->n_inotifiers)];
542 : 0 : return TRUE;
543 : : }
544 : 0 : return FALSE;
545 : : }
546 : :
547 : : /**
548 : : * g_closure_ref:
549 : : * @closure: #GClosure to increment the reference count on
550 : : *
551 : : * Increments the reference count on a closure to force it staying
552 : : * alive while the caller holds a pointer to it.
553 : : *
554 : : * Returns: (transfer none): The @closure passed in, for convenience
555 : : */
556 : : GClosure*
557 : 73006767 : g_closure_ref (GClosure *closure)
558 : : {
559 : : guint new_ref_count;
560 : 73006767 : g_return_val_if_fail (closure != NULL, NULL);
561 : 73006767 : g_return_val_if_fail (closure->ref_count > 0, NULL);
562 : 73006767 : g_return_val_if_fail (closure->ref_count < CLOSURE_MAX_REF_COUNT, NULL);
563 : :
564 [ + + ]: 78776063 : INC_ASSIGN (closure, ref_count, &new_ref_count);
565 : 73006767 : g_return_val_if_fail (new_ref_count > 1, NULL);
566 : :
567 : 73006767 : return closure;
568 : : }
569 : :
570 : : /**
571 : : * g_closure_invalidate:
572 : : * @closure: #GClosure to invalidate
573 : : *
574 : : * Sets a flag on the closure to indicate that its calling
575 : : * environment has become invalid, and thus causes any future
576 : : * invocations of g_closure_invoke() on this @closure to be
577 : : * ignored.
578 : : *
579 : : * Also, invalidation notifiers installed on the closure will
580 : : * be called at this point. Note that unless you are holding a
581 : : * reference to the closure yourself, the invalidation notifiers may
582 : : * unref the closure and cause it to be destroyed, so if you need to
583 : : * access the closure after calling g_closure_invalidate(), make sure
584 : : * that you've previously called g_closure_ref().
585 : : *
586 : : * Note that g_closure_invalidate() will also be called when the
587 : : * reference count of a closure drops to zero (unless it has already
588 : : * been invalidated before).
589 : : */
590 : : void
591 : 539497 : g_closure_invalidate (GClosure *closure)
592 : : {
593 : 539497 : g_return_if_fail (closure != NULL);
594 : :
595 [ + + ]: 539497 : if (!closure->is_invalid)
596 : : {
597 : : gboolean was_invalid;
598 : 539415 : g_closure_ref (closure); /* preserve floating flag */
599 [ - + ]: 539479 : SWAP (closure, is_invalid, TRUE, &was_invalid);
600 : : /* invalidate only once */
601 [ + # ]: 539479 : if (!was_invalid)
602 : 539490 : closure_invoke_notifiers (closure, INOTIFY);
603 : 539479 : g_closure_unref (closure);
604 : : }
605 : : }
606 : :
607 : : /**
608 : : * g_closure_unref:
609 : : * @closure: #GClosure to decrement the reference count on
610 : : *
611 : : * Decrements the reference count of a closure after it was previously
612 : : * incremented by the same caller.
613 : : *
614 : : * If no other callers are using the closure, then the closure will be
615 : : * destroyed and freed.
616 : : */
617 : : void
618 : 73683454 : g_closure_unref (GClosure *closure)
619 : : {
620 : : guint new_ref_count;
621 : :
622 : 73683454 : g_return_if_fail (closure != NULL);
623 : 73683454 : g_return_if_fail (closure->ref_count > 0);
624 : :
625 [ + + ]: 73683454 : if (closure->ref_count == 1) /* last unref, invalidate first */
626 : 539429 : g_closure_invalidate (closure);
627 : :
628 [ + + ]: 77974189 : DEC_ASSIGN (closure, ref_count, &new_ref_count);
629 : :
630 [ + + ]: 73439989 : if (new_ref_count == 0)
631 : : {
632 : 539500 : closure_invoke_notifiers (closure, FNOTIFY);
633 : 539388 : g_free (closure->notifiers);
634 : :
635 : : #ifdef ENABLE_VALGRIND
636 : : /* See comments in gtype.c about what's going on here... */
637 [ - + ]: 539472 : if (RUNNING_ON_VALGRIND)
638 : : {
639 : : gchar *allocated;
640 : :
641 : 0 : allocated = (gchar *) G_REAL_CLOSURE (closure);
642 : 0 : allocated -= sizeof (gpointer);
643 : :
644 : 0 : g_free (allocated);
645 : :
646 : 0 : VALGRIND_FREELIKE_BLOCK (allocated + sizeof (gpointer), 0);
647 : 0 : VALGRIND_FREELIKE_BLOCK (closure, 0);
648 : : }
649 : : else
650 : : #endif
651 : 539453 : g_free (G_REAL_CLOSURE (closure));
652 : : }
653 : : }
654 : :
655 : : /**
656 : : * g_closure_sink:
657 : : * @closure: #GClosure to decrement the initial reference count on, if it's
658 : : * still being held
659 : : *
660 : : * Takes over the initial ownership of a closure.
661 : : *
662 : : * Each closure is initially created in a "floating" state, which means
663 : : * that the initial reference count is not owned by any caller.
664 : : *
665 : : * This function checks to see if the object is still floating, and if so,
666 : : * unsets the floating state and decreases the reference count. If the
667 : : * closure is not floating, g_closure_sink() does nothing.
668 : : *
669 : : * The reason for the existence of the floating state is to prevent
670 : : * cumbersome code sequences like:
671 : : *
672 : : * |[<!-- language="C" -->
673 : : * closure = g_cclosure_new (cb_func, cb_data);
674 : : * g_source_set_closure (source, closure);
675 : : * g_closure_unref (closure); // GObject doesn't really need this
676 : : * ]|
677 : : *
678 : : * Because g_source_set_closure() (and similar functions) take ownership of the
679 : : * initial reference count, if it is unowned, we instead can write:
680 : : *
681 : : * |[<!-- language="C" -->
682 : : * g_source_set_closure (source, g_cclosure_new (cb_func, cb_data));
683 : : * ]|
684 : : *
685 : : * Generally, this function is used together with g_closure_ref(). An example
686 : : * of storing a closure for later notification looks like:
687 : : *
688 : : * |[<!-- language="C" -->
689 : : * static GClosure *notify_closure = NULL;
690 : : * void
691 : : * foo_notify_set_closure (GClosure *closure)
692 : : * {
693 : : * if (notify_closure)
694 : : * g_closure_unref (notify_closure);
695 : : * notify_closure = closure;
696 : : * if (notify_closure)
697 : : * {
698 : : * g_closure_ref (notify_closure);
699 : : * g_closure_sink (notify_closure);
700 : : * }
701 : : * }
702 : : * ]|
703 : : *
704 : : * Because g_closure_sink() may decrement the reference count of a closure
705 : : * (if it hasn't been called on @closure yet) just like g_closure_unref(),
706 : : * g_closure_ref() should be called prior to this function.
707 : : */
708 : : void
709 : 1016618 : g_closure_sink (GClosure *closure)
710 : : {
711 : 1016618 : g_return_if_fail (closure != NULL);
712 : 1016618 : g_return_if_fail (closure->ref_count > 0);
713 : :
714 : : /* floating is basically a kludge to avoid creating closures
715 : : * with a ref_count of 0. so the initial ref_count a closure has
716 : : * is unowned. with invoking g_closure_sink() code may
717 : : * indicate that it takes over that initial ref_count.
718 : : */
719 [ + + ]: 1016618 : if (closure->floating)
720 : : {
721 : : gboolean was_floating;
722 [ - + ]: 541608 : SWAP (closure, floating, FALSE, &was_floating);
723 : : /* unref floating flag only once */
724 [ + - ]: 541608 : if (was_floating)
725 : 541608 : g_closure_unref (closure);
726 : : }
727 : : }
728 : :
729 : : /**
730 : : * g_closure_remove_invalidate_notifier: (skip)
731 : : * @closure: a #GClosure
732 : : * @notify_data: data which was passed to g_closure_add_invalidate_notifier()
733 : : * when registering @notify_func
734 : : * @notify_func: the callback function to remove
735 : : *
736 : : * Removes an invalidation notifier.
737 : : *
738 : : * Notice that notifiers are automatically removed after they are run.
739 : : */
740 : : void
741 : 396 : g_closure_remove_invalidate_notifier (GClosure *closure,
742 : : gpointer notify_data,
743 : : GClosureNotify notify_func)
744 : : {
745 : 396 : g_return_if_fail (closure != NULL);
746 : 396 : g_return_if_fail (notify_func != NULL);
747 : :
748 [ - + - - ]: 396 : if (closure->is_invalid && closure->in_inotify && /* account removal of notify_func() while it's called */
749 [ # # ]: 0 : ((gpointer) closure->marshal) == ((gpointer) notify_func) &&
750 [ # # ]: 0 : closure->data == notify_data)
751 : 0 : closure->marshal = NULL;
752 [ - + ]: 396 : else if (!closure_try_remove_inotify (closure, notify_data, notify_func))
753 : 0 : g_critical (G_STRLOC ": unable to remove uninstalled invalidation notifier: %p (%p)",
754 : : notify_func, notify_data);
755 : : }
756 : :
757 : : /**
758 : : * g_closure_remove_finalize_notifier: (skip)
759 : : * @closure: a #GClosure
760 : : * @notify_data: data which was passed to g_closure_add_finalize_notifier()
761 : : * when registering @notify_func
762 : : * @notify_func: the callback function to remove
763 : : *
764 : : * Removes a finalization notifier.
765 : : *
766 : : * Notice that notifiers are automatically removed after they are run.
767 : : */
768 : : void
769 : 0 : g_closure_remove_finalize_notifier (GClosure *closure,
770 : : gpointer notify_data,
771 : : GClosureNotify notify_func)
772 : : {
773 : 0 : g_return_if_fail (closure != NULL);
774 : 0 : g_return_if_fail (notify_func != NULL);
775 : :
776 [ # # # # ]: 0 : if (closure->is_invalid && !closure->in_inotify && /* account removal of notify_func() while it's called */
777 [ # # ]: 0 : ((gpointer) closure->marshal) == ((gpointer) notify_func) &&
778 [ # # ]: 0 : closure->data == notify_data)
779 : 0 : closure->marshal = NULL;
780 [ # # ]: 0 : else if (!closure_try_remove_fnotify (closure, notify_data, notify_func))
781 : 0 : g_critical (G_STRLOC ": unable to remove uninstalled finalization notifier: %p (%p)",
782 : : notify_func, notify_data);
783 : : }
784 : :
785 : : /**
786 : : * g_closure_invoke:
787 : : * @closure: a #GClosure
788 : : * @return_value: (optional) (out): a #GValue to store the return
789 : : * value. May be %NULL if the callback of @closure
790 : : * doesn't return a value.
791 : : * @n_param_values: the length of the @param_values array
792 : : * @param_values: (array length=n_param_values): an array of
793 : : * #GValues holding the arguments on which to
794 : : * invoke the callback of @closure
795 : : * @invocation_hint: (nullable): a context-dependent invocation hint
796 : : *
797 : : * Invokes the closure, i.e. executes the callback represented by the @closure.
798 : : */
799 : : void
800 : 25134852 : g_closure_invoke (GClosure *closure,
801 : : GValue /*out*/ *return_value,
802 : : guint n_param_values,
803 : : const GValue *param_values,
804 : : gpointer invocation_hint)
805 : : {
806 : : GRealClosure *real_closure;
807 : :
808 : 25134852 : g_return_if_fail (closure != NULL);
809 : :
810 : 25134852 : real_closure = G_REAL_CLOSURE (closure);
811 : :
812 : 25134852 : g_closure_ref (closure); /* preserve floating flag */
813 [ + # ]: 25141053 : if (!closure->is_invalid)
814 : : {
815 : : GClosureMarshal marshal;
816 : : gpointer marshal_data;
817 : 25141547 : gboolean in_marshal = closure->in_marshal;
818 : :
819 : 25141547 : g_return_if_fail (closure->marshal || real_closure->meta_marshal);
820 : :
821 [ + + ]: 25639391 : SET (closure, in_marshal, TRUE);
822 [ + + ]: 25141547 : if (real_closure->meta_marshal)
823 : : {
824 : 15317456 : marshal_data = real_closure->meta_marshal_data;
825 : 15317456 : marshal = real_closure->meta_marshal;
826 : : }
827 : : else
828 : : {
829 : 9824091 : marshal_data = NULL;
830 : 9824091 : marshal = closure->marshal;
831 : : }
832 [ + + ]: 25141547 : if (!in_marshal)
833 : 19515811 : closure_invoke_notifiers (closure, PRE_NOTIFY);
834 : 25141192 : marshal (closure,
835 : : return_value,
836 : : n_param_values, param_values,
837 : : invocation_hint,
838 : : marshal_data);
839 [ + + ]: 25135996 : if (!in_marshal)
840 : 19515529 : closure_invoke_notifiers (closure, POST_NOTIFY);
841 [ + + ]: 25695889 : SET (closure, in_marshal, in_marshal);
842 : : }
843 : 25137795 : g_closure_unref (closure);
844 : : }
845 : :
846 : : gboolean
847 : 16634738 : _g_closure_supports_invoke_va (GClosure *closure)
848 : : {
849 : : GRealClosure *real_closure;
850 : :
851 : 16634738 : g_return_val_if_fail (closure != NULL, FALSE);
852 : :
853 : 16634738 : real_closure = G_REAL_CLOSURE (closure);
854 : :
855 : : return
856 [ + + ]: 22485887 : real_closure->va_marshal != NULL &&
857 [ + + ]: 5851149 : (real_closure->meta_marshal == NULL ||
858 [ + - ]: 1127271 : real_closure->va_meta_marshal != NULL);
859 : : }
860 : :
861 : : void
862 : 1213930 : _g_closure_invoke_va (GClosure *closure,
863 : : GValue /*out*/ *return_value,
864 : : gpointer instance,
865 : : va_list args,
866 : : int n_params,
867 : : GType *param_types)
868 : : {
869 : : GRealClosure *real_closure;
870 : :
871 : 1213930 : g_return_if_fail (closure != NULL);
872 : :
873 : 1213930 : real_closure = G_REAL_CLOSURE (closure);
874 : :
875 : 1213930 : g_closure_ref (closure); /* preserve floating flag */
876 [ + - ]: 1213930 : if (!closure->is_invalid)
877 : : {
878 : : GVaClosureMarshal marshal;
879 : : gpointer marshal_data;
880 : 1213930 : gboolean in_marshal = closure->in_marshal;
881 : :
882 : 1213930 : g_return_if_fail (closure->marshal || real_closure->meta_marshal);
883 : :
884 [ - + ]: 1213930 : SET (closure, in_marshal, TRUE);
885 [ + + ]: 1213930 : if (real_closure->va_meta_marshal)
886 : : {
887 : 572416 : marshal_data = real_closure->meta_marshal_data;
888 : 572416 : marshal = real_closure->va_meta_marshal;
889 : : }
890 : : else
891 : : {
892 : 641514 : marshal_data = NULL;
893 : 641514 : marshal = real_closure->va_marshal;
894 : : }
895 [ + - ]: 1213930 : if (!in_marshal)
896 : 1213930 : closure_invoke_notifiers (closure, PRE_NOTIFY);
897 : 1213929 : marshal (closure,
898 : : return_value,
899 : : instance, args,
900 : : marshal_data,
901 : : n_params, param_types);
902 [ + - ]: 1213928 : if (!in_marshal)
903 : 1213928 : closure_invoke_notifiers (closure, POST_NOTIFY);
904 [ - + ]: 1213928 : SET (closure, in_marshal, in_marshal);
905 : : }
906 : 1213928 : g_closure_unref (closure);
907 : : }
908 : :
909 : :
910 : : /**
911 : : * g_closure_set_marshal: (skip)
912 : : * @closure: a #GClosure
913 : : * @marshal: a #GClosureMarshal function
914 : : *
915 : : * Sets the marshaller of @closure.
916 : : *
917 : : * The `marshal_data` of @marshal provides a way for a meta marshaller to
918 : : * provide additional information to the marshaller.
919 : : *
920 : : * For GObject's C predefined marshallers (the `g_cclosure_marshal_*()`
921 : : * functions), what it provides is a callback function to use instead of
922 : : * @closure->callback.
923 : : *
924 : : * See also: g_closure_set_meta_marshal()
925 : : */
926 : : void
927 : 541603 : g_closure_set_marshal (GClosure *closure,
928 : : GClosureMarshal marshal)
929 : : {
930 : 541603 : g_return_if_fail (closure != NULL);
931 : 541603 : g_return_if_fail (marshal != NULL);
932 : :
933 [ - + - - ]: 541603 : if (closure->marshal && closure->marshal != marshal)
934 : 0 : g_critical ("attempt to override closure->marshal (%p) with new marshal (%p)",
935 : : closure->marshal, marshal);
936 : : else
937 : 541603 : closure->marshal = marshal;
938 : : }
939 : :
940 : : void
941 : 522658 : _g_closure_set_va_marshal (GClosure *closure,
942 : : GVaClosureMarshal marshal)
943 : : {
944 : : GRealClosure *real_closure;
945 : :
946 : 522658 : g_return_if_fail (closure != NULL);
947 : 522658 : g_return_if_fail (marshal != NULL);
948 : :
949 : 522658 : real_closure = G_REAL_CLOSURE (closure);
950 : :
951 [ - + - - ]: 522658 : if (real_closure->va_marshal && real_closure->va_marshal != marshal)
952 : 0 : g_critical ("attempt to override closure->va_marshal (%p) with new marshal (%p)",
953 : : real_closure->va_marshal, marshal);
954 : : else
955 : 522658 : real_closure->va_marshal = marshal;
956 : : }
957 : :
958 : : /**
959 : : * g_cclosure_new: (skip)
960 : : * @callback_func: the function to invoke
961 : : * @user_data: (closure callback_func): user data to pass to @callback_func
962 : : * @destroy_data: destroy notify to be called when @user_data is no longer used
963 : : *
964 : : * Creates a new closure which invokes @callback_func with @user_data as
965 : : * the last parameter.
966 : : *
967 : : * @destroy_data will be called as a finalize notifier on the #GClosure.
968 : : *
969 : : * Returns: (transfer floating): a floating reference to a new #GCClosure
970 : : */
971 : : GClosure*
972 : 521063 : g_cclosure_new (GCallback callback_func,
973 : : gpointer user_data,
974 : : GClosureNotify destroy_data)
975 : : {
976 : : GClosure *closure;
977 : :
978 : 521063 : g_return_val_if_fail (callback_func != NULL, NULL);
979 : :
980 : 521063 : closure = g_closure_new_simple (sizeof (GCClosure), user_data);
981 [ + + ]: 521063 : if (destroy_data)
982 : 2167 : g_closure_add_finalize_notifier (closure, user_data, destroy_data);
983 : 521063 : ((GCClosure*) closure)->callback = (gpointer) callback_func;
984 : :
985 : 521063 : return closure;
986 : : }
987 : :
988 : : /**
989 : : * g_cclosure_new_swap: (skip)
990 : : * @callback_func: the function to invoke
991 : : * @user_data: (closure callback_func): user data to pass to @callback_func
992 : : * @destroy_data: destroy notify to be called when @user_data is no longer used
993 : : *
994 : : * Creates a new closure which invokes @callback_func with @user_data as
995 : : * the first parameter.
996 : : *
997 : : * @destroy_data will be called as a finalize notifier on the #GClosure.
998 : : *
999 : : * Returns: (transfer floating): a floating reference to a new #GCClosure
1000 : : */
1001 : : GClosure*
1002 : 216 : g_cclosure_new_swap (GCallback callback_func,
1003 : : gpointer user_data,
1004 : : GClosureNotify destroy_data)
1005 : : {
1006 : : GClosure *closure;
1007 : :
1008 : 216 : g_return_val_if_fail (callback_func != NULL, NULL);
1009 : :
1010 : 216 : closure = g_closure_new_simple (sizeof (GCClosure), user_data);
1011 [ - + ]: 216 : if (destroy_data)
1012 : 0 : g_closure_add_finalize_notifier (closure, user_data, destroy_data);
1013 : 216 : ((GCClosure*) closure)->callback = (gpointer) callback_func;
1014 [ - + ]: 216 : SET (closure, derivative_flag, TRUE);
1015 : :
1016 : 216 : return closure;
1017 : : }
1018 : :
1019 : : static void
1020 : 15210092 : g_type_class_meta_marshal (GClosure *closure,
1021 : : GValue /*out*/ *return_value,
1022 : : guint n_param_values,
1023 : : const GValue *param_values,
1024 : : gpointer invocation_hint,
1025 : : gpointer marshal_data)
1026 : : {
1027 : : GTypeClass *class;
1028 : : gpointer callback;
1029 : : /* GType itype = (GType) closure->data; */
1030 : 15210092 : guint offset = GPOINTER_TO_UINT (marshal_data);
1031 : :
1032 : 15210092 : class = G_TYPE_INSTANCE_GET_CLASS (g_value_peek_pointer (param_values + 0), itype, GTypeClass);
1033 : 15207627 : callback = G_STRUCT_MEMBER (gpointer, class, offset);
1034 [ + + ]: 15207627 : if (callback)
1035 : 8851140 : closure->marshal (closure,
1036 : : return_value,
1037 : : n_param_values, param_values,
1038 : : invocation_hint,
1039 : : callback);
1040 : 15205983 : }
1041 : :
1042 : : static void
1043 : 572416 : g_type_class_meta_marshalv (GClosure *closure,
1044 : : GValue *return_value,
1045 : : gpointer instance,
1046 : : va_list args,
1047 : : gpointer marshal_data,
1048 : : int n_params,
1049 : : GType *param_types)
1050 : : {
1051 : : GRealClosure *real_closure;
1052 : : GTypeClass *class;
1053 : : gpointer callback;
1054 : : /* GType itype = (GType) closure->data; */
1055 : 572416 : guint offset = GPOINTER_TO_UINT (marshal_data);
1056 : :
1057 : 572416 : real_closure = G_REAL_CLOSURE (closure);
1058 : :
1059 : 572416 : class = G_TYPE_INSTANCE_GET_CLASS (instance, itype, GTypeClass);
1060 : 572416 : callback = G_STRUCT_MEMBER (gpointer, class, offset);
1061 [ + - ]: 572416 : if (callback)
1062 : 572416 : real_closure->va_marshal (closure,
1063 : : return_value,
1064 : : instance, args,
1065 : : callback,
1066 : : n_params,
1067 : : param_types);
1068 : 572416 : }
1069 : :
1070 : : static void
1071 : 100247 : g_type_iface_meta_marshal (GClosure *closure,
1072 : : GValue /*out*/ *return_value,
1073 : : guint n_param_values,
1074 : : const GValue *param_values,
1075 : : gpointer invocation_hint,
1076 : : gpointer marshal_data)
1077 : : {
1078 : : GTypeClass *class;
1079 : : gpointer callback;
1080 : 100247 : GType itype = (GType) closure->data;
1081 : 100247 : guint offset = GPOINTER_TO_UINT (marshal_data);
1082 : :
1083 : 100247 : class = G_TYPE_INSTANCE_GET_INTERFACE (g_value_peek_pointer (param_values + 0), itype, GTypeClass);
1084 : 100216 : callback = G_STRUCT_MEMBER (gpointer, class, offset);
1085 [ + + ]: 100216 : if (callback)
1086 : 78 : closure->marshal (closure,
1087 : : return_value,
1088 : : n_param_values, param_values,
1089 : : invocation_hint,
1090 : : callback);
1091 : 100216 : }
1092 : :
1093 : : gboolean
1094 : 24992698 : _g_closure_is_void (GClosure *closure,
1095 : : gpointer instance)
1096 : : {
1097 : : GRealClosure *real_closure;
1098 : : GTypeClass *class;
1099 : : gpointer callback;
1100 : : GType itype;
1101 : : guint offset;
1102 : :
1103 [ - + ]: 24992698 : if (closure->is_invalid)
1104 : 0 : return TRUE;
1105 : :
1106 : 24992698 : real_closure = G_REAL_CLOSURE (closure);
1107 : :
1108 [ - + ]: 24992698 : if (real_closure->meta_marshal == g_type_iface_meta_marshal)
1109 : : {
1110 : 0 : itype = (GType) closure->data;
1111 : 0 : offset = GPOINTER_TO_UINT (real_closure->meta_marshal_data);
1112 : :
1113 : 0 : class = G_TYPE_INSTANCE_GET_INTERFACE (instance, itype, GTypeClass);
1114 : 0 : callback = G_STRUCT_MEMBER (gpointer, class, offset);
1115 : 0 : return callback == NULL;
1116 : : }
1117 [ + + ]: 24992698 : else if (real_closure->meta_marshal == g_type_class_meta_marshal)
1118 : : {
1119 : 24992697 : offset = GPOINTER_TO_UINT (real_closure->meta_marshal_data);
1120 : :
1121 : 24992697 : class = G_TYPE_INSTANCE_GET_CLASS (instance, itype, GTypeClass);
1122 : 24992697 : callback = G_STRUCT_MEMBER (gpointer, class, offset);
1123 : 24992697 : return callback == NULL;
1124 : : }
1125 : :
1126 : 1 : return FALSE;
1127 : : }
1128 : :
1129 : : static void
1130 : 0 : g_type_iface_meta_marshalv (GClosure *closure,
1131 : : GValue *return_value,
1132 : : gpointer instance,
1133 : : va_list args,
1134 : : gpointer marshal_data,
1135 : : int n_params,
1136 : : GType *param_types)
1137 : : {
1138 : : GRealClosure *real_closure;
1139 : : GTypeClass *class;
1140 : : gpointer callback;
1141 : 0 : GType itype = (GType) closure->data;
1142 : 0 : guint offset = GPOINTER_TO_UINT (marshal_data);
1143 : :
1144 : 0 : real_closure = G_REAL_CLOSURE (closure);
1145 : :
1146 : 0 : class = G_TYPE_INSTANCE_GET_INTERFACE (instance, itype, GTypeClass);
1147 : 0 : callback = G_STRUCT_MEMBER (gpointer, class, offset);
1148 [ # # ]: 0 : if (callback)
1149 : 0 : real_closure->va_marshal (closure,
1150 : : return_value,
1151 : : instance, args,
1152 : : callback,
1153 : : n_params,
1154 : : param_types);
1155 : 0 : }
1156 : :
1157 : : /**
1158 : : * g_signal_type_cclosure_new:
1159 : : * @itype: the #GType identifier of an interface or classed type
1160 : : * @struct_offset: the offset of the member function of @itype's class
1161 : : * structure which is to be invoked by the new closure
1162 : : *
1163 : : * Creates a new closure which invokes the function found at the offset
1164 : : * @struct_offset in the class structure of the interface or classed type
1165 : : * identified by @itype.
1166 : : *
1167 : : * Returns: (transfer floating): a floating reference to a new #GCClosure
1168 : : */
1169 : : GClosure*
1170 : 1632 : g_signal_type_cclosure_new (GType itype,
1171 : : guint struct_offset)
1172 : : {
1173 : : GClosure *closure;
1174 : :
1175 : 1632 : g_return_val_if_fail (G_TYPE_IS_CLASSED (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
1176 : 1632 : g_return_val_if_fail (struct_offset >= sizeof (GTypeClass), NULL);
1177 : :
1178 : 1632 : closure = g_closure_new_simple (sizeof (GClosure), GTYPE_TO_POINTER (itype));
1179 [ + + ]: 1632 : if (G_TYPE_IS_INTERFACE (itype))
1180 : : {
1181 : 184 : g_closure_set_meta_marshal (closure, GUINT_TO_POINTER (struct_offset), g_type_iface_meta_marshal);
1182 : 184 : g_closure_set_meta_va_marshal (closure, g_type_iface_meta_marshalv);
1183 : : }
1184 : : else
1185 : : {
1186 : 1448 : g_closure_set_meta_marshal (closure, GUINT_TO_POINTER (struct_offset), g_type_class_meta_marshal);
1187 : 1448 : g_closure_set_meta_va_marshal (closure, g_type_class_meta_marshalv);
1188 : : }
1189 : 1632 : return closure;
1190 : : }
1191 : :
1192 : : #include <ffi.h>
1193 : : static ffi_type *
1194 : 6764571 : value_to_ffi_type (const GValue *gvalue,
1195 : : gpointer *value,
1196 : : gint *enum_tmpval,
1197 : : gboolean *tmpval_used)
1198 : : {
1199 : 6764571 : ffi_type *rettype = NULL;
1200 : 6764571 : GType type = g_type_fundamental (G_VALUE_TYPE (gvalue));
1201 : 6783076 : g_assert (type != G_TYPE_INVALID);
1202 : :
1203 [ + + ]: 6785229 : if (enum_tmpval)
1204 : : {
1205 : 6782855 : g_assert (tmpval_used != NULL);
1206 : 6782855 : *tmpval_used = FALSE;
1207 : : }
1208 : :
1209 [ + + + + : 6785229 : switch (type)
+ + + + +
+ + - ]
1210 : : {
1211 : 2262077 : case G_TYPE_BOOLEAN:
1212 : : case G_TYPE_CHAR:
1213 : : case G_TYPE_INT:
1214 : 2262077 : rettype = &ffi_type_sint;
1215 : 2262077 : *value = (gpointer)&(gvalue->data[0].v_int);
1216 : 2262077 : break;
1217 : 9 : case G_TYPE_ENUM:
1218 : : /* enums are stored in v_long even though they are integers, which makes
1219 : : * marshalling through libffi somewhat complicated. They need to be
1220 : : * marshalled as signed ints, but we need to use a temporary int sized
1221 : : * value to pass to libffi otherwise it'll pull the wrong value on
1222 : : * BE machines with 32-bit integers when treating v_long as 32-bit int.
1223 : : */
1224 : 9 : g_assert (enum_tmpval != NULL);
1225 : 9 : rettype = &ffi_type_sint;
1226 : 9 : *enum_tmpval = g_value_get_enum (gvalue);
1227 : 9 : *value = enum_tmpval;
1228 : 9 : *tmpval_used = TRUE;
1229 : 9 : break;
1230 : 7 : case G_TYPE_FLAGS:
1231 : 7 : g_assert (enum_tmpval != NULL);
1232 : 7 : rettype = &ffi_type_uint;
1233 : 7 : *enum_tmpval = g_value_get_flags (gvalue);
1234 : 7 : *value = enum_tmpval;
1235 : 7 : *tmpval_used = TRUE;
1236 : 7 : break;
1237 : 12 : case G_TYPE_UCHAR:
1238 : : case G_TYPE_UINT:
1239 : 12 : rettype = &ffi_type_uint;
1240 : 12 : *value = (gpointer)&(gvalue->data[0].v_uint);
1241 : 12 : break;
1242 : 4523093 : case G_TYPE_STRING:
1243 : : case G_TYPE_OBJECT:
1244 : : case G_TYPE_BOXED:
1245 : : case G_TYPE_PARAM:
1246 : : case G_TYPE_POINTER:
1247 : : case G_TYPE_INTERFACE:
1248 : : case G_TYPE_VARIANT:
1249 : 4523093 : rettype = &ffi_type_pointer;
1250 : 4523093 : *value = (gpointer)&(gvalue->data[0].v_pointer);
1251 : 4523093 : break;
1252 : 5 : case G_TYPE_FLOAT:
1253 : 5 : rettype = &ffi_type_float;
1254 : 5 : *value = (gpointer)&(gvalue->data[0].v_float);
1255 : 5 : break;
1256 : 5 : case G_TYPE_DOUBLE:
1257 : 5 : rettype = &ffi_type_double;
1258 : 5 : *value = (gpointer)&(gvalue->data[0].v_double);
1259 : 5 : break;
1260 : 5 : case G_TYPE_LONG:
1261 : 5 : rettype = &ffi_type_slong;
1262 : 5 : *value = (gpointer)&(gvalue->data[0].v_long);
1263 : 5 : break;
1264 : 6 : case G_TYPE_ULONG:
1265 : 6 : rettype = &ffi_type_ulong;
1266 : 6 : *value = (gpointer)&(gvalue->data[0].v_ulong);
1267 : 6 : break;
1268 : 5 : case G_TYPE_INT64:
1269 : 5 : rettype = &ffi_type_sint64;
1270 : 5 : *value = (gpointer)&(gvalue->data[0].v_int64);
1271 : 5 : break;
1272 : 5 : case G_TYPE_UINT64:
1273 : 5 : rettype = &ffi_type_uint64;
1274 : 5 : *value = (gpointer)&(gvalue->data[0].v_uint64);
1275 : 5 : break;
1276 : 0 : default:
1277 : 0 : rettype = &ffi_type_pointer;
1278 : 0 : *value = NULL;
1279 : 0 : g_critical ("value_to_ffi_type: Unsupported fundamental type: %s", g_type_name (type));
1280 : 0 : break;
1281 : : }
1282 : 6783056 : return rettype;
1283 : : }
1284 : :
1285 : : static void
1286 : 2263105 : value_from_ffi_type (GValue *gvalue, gpointer *value)
1287 : : {
1288 : 2263105 : ffi_arg *int_val = (ffi_arg*) value;
1289 : : GType type;
1290 : :
1291 : 2263105 : type = G_VALUE_TYPE (gvalue);
1292 : :
1293 : 2263106 : restart:
1294 [ + - - + : 2263106 : switch (g_type_fundamental (type))
+ - - + -
- - - - -
+ - - + +
+ # ]
1295 : : {
1296 : 7 : case G_TYPE_INT:
1297 : 7 : g_value_set_int (gvalue, (gint) *int_val);
1298 : 7 : break;
1299 : 0 : case G_TYPE_FLOAT:
1300 : 0 : g_value_set_float (gvalue, *(gfloat*)value);
1301 : 0 : break;
1302 : 0 : case G_TYPE_DOUBLE:
1303 : 0 : g_value_set_double (gvalue, *(gdouble*)value);
1304 : 0 : break;
1305 : 20 : case G_TYPE_BOOLEAN:
1306 : 20 : g_value_set_boolean (gvalue, (gboolean) *int_val);
1307 : 20 : break;
1308 : 2262808 : case G_TYPE_STRING:
1309 : 2262808 : g_value_take_string (gvalue, *(gchar**)value);
1310 : 2262734 : break;
1311 : 0 : case G_TYPE_CHAR:
1312 : 0 : g_value_set_schar (gvalue, (gint8) *int_val);
1313 : 0 : break;
1314 : 0 : case G_TYPE_UCHAR:
1315 : 0 : g_value_set_uchar (gvalue, (guchar) *int_val);
1316 : 0 : break;
1317 : 2 : case G_TYPE_UINT:
1318 : 2 : g_value_set_uint (gvalue, (guint) *int_val);
1319 : 2 : break;
1320 : 0 : case G_TYPE_POINTER:
1321 : 0 : g_value_set_pointer (gvalue, *(gpointer*)value);
1322 : 0 : break;
1323 : 0 : case G_TYPE_LONG:
1324 : 0 : g_value_set_long (gvalue, (glong) *int_val);
1325 : 0 : break;
1326 : 0 : case G_TYPE_ULONG:
1327 : 0 : g_value_set_ulong (gvalue, (gulong) *int_val);
1328 : 0 : break;
1329 : 0 : case G_TYPE_INT64:
1330 : 0 : g_value_set_int64 (gvalue, (gint64) *int_val);
1331 : 0 : break;
1332 : 0 : case G_TYPE_UINT64:
1333 : 0 : g_value_set_uint64 (gvalue, (guint64) *int_val);
1334 : 0 : break;
1335 : 0 : case G_TYPE_BOXED:
1336 : 0 : g_value_take_boxed (gvalue, *(gpointer*)value);
1337 : 0 : break;
1338 : 4 : case G_TYPE_ENUM:
1339 : 4 : g_value_set_enum (gvalue, (gint) *int_val);
1340 : 4 : break;
1341 : 0 : case G_TYPE_FLAGS:
1342 : 0 : g_value_set_flags (gvalue, (guint) *int_val);
1343 : 0 : break;
1344 : 0 : case G_TYPE_PARAM:
1345 : 0 : g_value_take_param (gvalue, *(gpointer*)value);
1346 : 0 : break;
1347 : 1 : case G_TYPE_OBJECT:
1348 : 1 : g_value_take_object (gvalue, *(gpointer*)value);
1349 : 1 : break;
1350 : 3 : case G_TYPE_VARIANT:
1351 : 3 : g_value_take_variant (gvalue, *(gpointer*)value);
1352 : 3 : break;
1353 : 1 : case G_TYPE_INTERFACE:
1354 : 1 : type = g_type_interface_instantiatable_prerequisite (type);
1355 [ + - ]: 1 : if (type)
1356 : 1 : goto restart;
1357 : : G_GNUC_FALLTHROUGH;
1358 : : default:
1359 : 0 : g_critical ("value_from_ffi_type: Unsupported fundamental type %s for type %s",
1360 : : g_type_name (g_type_fundamental (G_VALUE_TYPE (gvalue))),
1361 : : g_type_name (G_VALUE_TYPE (gvalue)));
1362 : : }
1363 : 2262771 : }
1364 : :
1365 : : typedef union {
1366 : : gpointer _gpointer;
1367 : : float _float;
1368 : : double _double;
1369 : : gint _gint;
1370 : : guint _guint;
1371 : : glong _glong;
1372 : : gulong _gulong;
1373 : : gint64 _gint64;
1374 : : guint64 _guint64;
1375 : : } va_arg_storage;
1376 : :
1377 : : static ffi_type *
1378 : 31 : va_to_ffi_type (GType gtype,
1379 : : va_list *va,
1380 : : va_arg_storage *storage)
1381 : : {
1382 : 31 : ffi_type *rettype = NULL;
1383 : 31 : GType type = g_type_fundamental (gtype);
1384 : 31 : g_assert (type != G_TYPE_INVALID);
1385 : :
1386 [ + + + + : 31 : switch (type)
+ + + + +
- ]
1387 : : {
1388 : 11 : case G_TYPE_BOOLEAN:
1389 : : case G_TYPE_CHAR:
1390 : : case G_TYPE_INT:
1391 : : case G_TYPE_ENUM:
1392 : 11 : rettype = &ffi_type_sint;
1393 : 11 : storage->_gint = va_arg (*va, gint);
1394 : 11 : break;
1395 : 4 : case G_TYPE_UCHAR:
1396 : : case G_TYPE_UINT:
1397 : : case G_TYPE_FLAGS:
1398 : 4 : rettype = &ffi_type_uint;
1399 : 4 : storage->_guint = va_arg (*va, guint);
1400 : 4 : break;
1401 : 7 : case G_TYPE_STRING:
1402 : : case G_TYPE_OBJECT:
1403 : : case G_TYPE_BOXED:
1404 : : case G_TYPE_PARAM:
1405 : : case G_TYPE_POINTER:
1406 : : case G_TYPE_INTERFACE:
1407 : : case G_TYPE_VARIANT:
1408 : 7 : rettype = &ffi_type_pointer;
1409 : 7 : storage->_gpointer = va_arg (*va, gpointer);
1410 : 7 : break;
1411 : 2 : case G_TYPE_FLOAT:
1412 : : /* Float args are passed as doubles in varargs */
1413 : 2 : rettype = &ffi_type_float;
1414 : 2 : storage->_float = (float)va_arg (*va, double);
1415 : 2 : break;
1416 : 2 : case G_TYPE_DOUBLE:
1417 : 2 : rettype = &ffi_type_double;
1418 : 2 : storage->_double = va_arg (*va, double);
1419 : 2 : break;
1420 : 2 : case G_TYPE_LONG:
1421 : 2 : rettype = &ffi_type_slong;
1422 : 2 : storage->_glong = va_arg (*va, glong);
1423 : 2 : break;
1424 : 1 : case G_TYPE_ULONG:
1425 : 1 : rettype = &ffi_type_ulong;
1426 : 1 : storage->_gulong = va_arg (*va, gulong);
1427 : 1 : break;
1428 : 1 : case G_TYPE_INT64:
1429 : 1 : rettype = &ffi_type_sint64;
1430 : 1 : storage->_gint64 = va_arg (*va, gint64);
1431 : 1 : break;
1432 : 1 : case G_TYPE_UINT64:
1433 : 1 : rettype = &ffi_type_uint64;
1434 : 1 : storage->_guint64 = va_arg (*va, guint64);
1435 : 1 : break;
1436 : 0 : default:
1437 : 0 : rettype = &ffi_type_pointer;
1438 : 0 : storage->_guint64 = 0;
1439 : 0 : g_critical ("va_to_ffi_type: Unsupported fundamental type: %s", g_type_name (type));
1440 : 0 : break;
1441 : : }
1442 : 31 : return rettype;
1443 : : }
1444 : :
1445 : : /**
1446 : : * g_cclosure_marshal_generic:
1447 : : * @closure: A #GClosure.
1448 : : * @return_gvalue: A #GValue to store the return value. May be %NULL
1449 : : * if the callback of closure doesn't return a value.
1450 : : * @n_param_values: The length of the @param_values array.
1451 : : * @param_values: An array of #GValues holding the arguments
1452 : : * on which to invoke the callback of closure.
1453 : : * @invocation_hint: The invocation hint given as the last argument to
1454 : : * g_closure_invoke().
1455 : : * @marshal_data: Additional data specified when registering the
1456 : : * marshaller, see g_closure_set_marshal() and
1457 : : * g_closure_set_meta_marshal()
1458 : : *
1459 : : * A generic marshaller function implemented via
1460 : : * [libffi](http://sourceware.org/libffi/).
1461 : : *
1462 : : * Normally this function is not passed explicitly to g_signal_new(),
1463 : : * but used automatically by GLib when specifying a %NULL marshaller.
1464 : : *
1465 : : * Since: 2.30
1466 : : */
1467 : : void
1468 : 2262497 : g_cclosure_marshal_generic (GClosure *closure,
1469 : : GValue *return_gvalue,
1470 : : guint n_param_values,
1471 : : const GValue *param_values,
1472 : : gpointer invocation_hint,
1473 : : gpointer marshal_data)
1474 : : {
1475 : : ffi_type *rtype;
1476 : : void *rvalue;
1477 : : int n_args;
1478 : : ffi_type **atypes;
1479 : : void **args;
1480 : : int i;
1481 : : ffi_cif cif;
1482 : 2262497 : GCClosure *cc = (GCClosure*) closure;
1483 : : gint *enum_tmpval;
1484 : 2262497 : gboolean tmpval_used = FALSE;
1485 : :
1486 : 2262497 : enum_tmpval = g_alloca (sizeof (gint));
1487 [ + # + # ]: 2262497 : if (return_gvalue && G_VALUE_TYPE (return_gvalue))
1488 : : {
1489 : 2262581 : rtype = value_to_ffi_type (return_gvalue, &rvalue, enum_tmpval, &tmpval_used);
1490 : : }
1491 : : else
1492 : : {
1493 : 0 : rtype = &ffi_type_void;
1494 : : }
1495 : :
1496 : 2262485 : rvalue = g_alloca (MAX (rtype->size, sizeof (ffi_arg)));
1497 : :
1498 : 2262485 : n_args = n_param_values + 1;
1499 : 2262485 : atypes = g_alloca (sizeof (ffi_type *) * n_args);
1500 : 2262485 : args = g_alloca (sizeof (gpointer) * n_args);
1501 : :
1502 [ - + ]: 2262485 : if (tmpval_used)
1503 : 0 : enum_tmpval = g_alloca (sizeof (gint));
1504 : :
1505 [ - + ]: 2262485 : if (G_CCLOSURE_SWAP_DATA (closure))
1506 : : {
1507 : 0 : atypes[n_args-1] = value_to_ffi_type (param_values + 0,
1508 : 0 : &args[n_args-1],
1509 : : enum_tmpval,
1510 : : &tmpval_used);
1511 : 0 : atypes[0] = &ffi_type_pointer;
1512 : 0 : args[0] = &closure->data;
1513 : : }
1514 : : else
1515 : : {
1516 : 2262485 : atypes[0] = value_to_ffi_type (param_values + 0,
1517 : : &args[0],
1518 : : enum_tmpval,
1519 : : &tmpval_used);
1520 : 2262085 : atypes[n_args-1] = &ffi_type_pointer;
1521 : 2262085 : args[n_args-1] = &closure->data;
1522 : : }
1523 : :
1524 [ + + ]: 4524304 : for (i = 1; i < n_args - 1; i++)
1525 : : {
1526 [ + + ]: 2262184 : if (tmpval_used)
1527 : 10 : enum_tmpval = g_alloca (sizeof (gint));
1528 : :
1529 : 2262219 : atypes[i] = value_to_ffi_type (param_values + i,
1530 : 2262184 : &args[i],
1531 : : enum_tmpval,
1532 : : &tmpval_used);
1533 : : }
1534 : :
1535 [ - + ]: 2262120 : if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_args, rtype, atypes) != FFI_OK)
1536 : 0 : return;
1537 : :
1538 [ + + ]: 2262576 : ffi_call (&cif, marshal_data ? marshal_data : cc->callback, rvalue, args);
1539 : :
1540 [ + # + + ]: 2262903 : if (return_gvalue && G_VALUE_TYPE (return_gvalue))
1541 : 2262973 : value_from_ffi_type (return_gvalue, rvalue);
1542 : : }
1543 : :
1544 : : /**
1545 : : * g_cclosure_marshal_generic_va:
1546 : : * @closure: the #GClosure to which the marshaller belongs
1547 : : * @return_value: (nullable): a #GValue to store the return
1548 : : * value. May be %NULL if the callback of @closure doesn't return a
1549 : : * value.
1550 : : * @instance: (type GObject.TypeInstance): the instance on which the closure is
1551 : : * invoked.
1552 : : * @args_list: va_list of arguments to be passed to the closure.
1553 : : * @marshal_data: (nullable): additional data specified when
1554 : : * registering the marshaller, see g_closure_set_marshal() and
1555 : : * g_closure_set_meta_marshal()
1556 : : * @n_params: the length of the @param_types array
1557 : : * @param_types: (array length=n_params): the #GType of each argument from
1558 : : * @args_list.
1559 : : *
1560 : : * A generic #GVaClosureMarshal function implemented via
1561 : : * [libffi](http://sourceware.org/libffi/).
1562 : : *
1563 : : * Since: 2.30
1564 : : */
1565 : : void
1566 : 13 : g_cclosure_marshal_generic_va (GClosure *closure,
1567 : : GValue *return_value,
1568 : : gpointer instance,
1569 : : va_list args_list,
1570 : : gpointer marshal_data,
1571 : : int n_params,
1572 : : GType *param_types)
1573 : : {
1574 : : ffi_type *rtype;
1575 : : void *rvalue;
1576 : : int n_args;
1577 : : ffi_type **atypes;
1578 : : void **args;
1579 : : va_arg_storage *storage;
1580 : : int i;
1581 : : ffi_cif cif;
1582 : 13 : GCClosure *cc = (GCClosure*) closure;
1583 : : gint *enum_tmpval;
1584 : 13 : gboolean tmpval_used = FALSE;
1585 : : va_list args_copy;
1586 : :
1587 : 13 : enum_tmpval = g_alloca (sizeof (gint));
1588 [ + + + - ]: 13 : if (return_value && G_VALUE_TYPE (return_value))
1589 : : {
1590 : 10 : rtype = value_to_ffi_type (return_value, &rvalue, enum_tmpval, &tmpval_used);
1591 : : }
1592 : : else
1593 : : {
1594 : 3 : rtype = &ffi_type_void;
1595 : : }
1596 : :
1597 : 13 : rvalue = g_alloca (MAX (rtype->size, sizeof (ffi_arg)));
1598 : :
1599 : 13 : n_args = n_params + 2;
1600 : 13 : atypes = g_alloca (sizeof (ffi_type *) * n_args);
1601 : 13 : args = g_alloca (sizeof (gpointer) * n_args);
1602 : 13 : storage = g_alloca (sizeof (va_arg_storage) * n_params);
1603 : :
1604 [ - + ]: 13 : if (G_CCLOSURE_SWAP_DATA (closure))
1605 : : {
1606 : 0 : atypes[n_args-1] = &ffi_type_pointer;
1607 : 0 : args[n_args-1] = &instance;
1608 : 0 : atypes[0] = &ffi_type_pointer;
1609 : 0 : args[0] = &closure->data;
1610 : : }
1611 : : else
1612 : : {
1613 : 13 : atypes[0] = &ffi_type_pointer;
1614 : 13 : args[0] = &instance;
1615 : 13 : atypes[n_args-1] = &ffi_type_pointer;
1616 : 13 : args[n_args-1] = &closure->data;
1617 : : }
1618 : :
1619 : 13 : va_copy (args_copy, args_list);
1620 : :
1621 : : /* Box non-primitive arguments */
1622 [ + + ]: 44 : for (i = 0; i < n_params; i++)
1623 : : {
1624 : 31 : GType type = param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
1625 : 31 : GType fundamental = G_TYPE_FUNDAMENTAL (type);
1626 : :
1627 : 62 : atypes[i+1] = va_to_ffi_type (type,
1628 : : &args_copy,
1629 : 31 : &storage[i]);
1630 : 31 : args[i+1] = &storage[i];
1631 : :
1632 [ + - ]: 31 : if ((param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0)
1633 : : {
1634 [ + + + - ]: 31 : if (fundamental == G_TYPE_STRING && storage[i]._gpointer != NULL)
1635 : 2 : storage[i]._gpointer = g_strdup (storage[i]._gpointer);
1636 [ + + + - ]: 30 : else if (fundamental == G_TYPE_PARAM && storage[i]._gpointer != NULL)
1637 : 1 : storage[i]._gpointer = g_param_spec_ref (storage[i]._gpointer);
1638 [ + + + - ]: 29 : else if (fundamental == G_TYPE_BOXED && storage[i]._gpointer != NULL)
1639 : 1 : storage[i]._gpointer = g_boxed_copy (type, storage[i]._gpointer);
1640 [ + + + - ]: 28 : else if (fundamental == G_TYPE_VARIANT && storage[i]._gpointer != NULL)
1641 : 1 : storage[i]._gpointer = g_variant_ref_sink (storage[i]._gpointer);
1642 : : }
1643 [ + + + - ]: 31 : if (fundamental == G_TYPE_OBJECT && storage[i]._gpointer != NULL)
1644 : 1 : storage[i]._gpointer = g_object_ref (storage[i]._gpointer);
1645 : : }
1646 : :
1647 : 13 : va_end (args_copy);
1648 : :
1649 [ - + ]: 13 : if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_args, rtype, atypes) != FFI_OK)
1650 : 0 : return;
1651 : :
1652 [ + + ]: 13 : ffi_call (&cif, marshal_data ? marshal_data : cc->callback, rvalue, args);
1653 : :
1654 : : /* Unbox non-primitive arguments */
1655 [ + + ]: 44 : for (i = 0; i < n_params; i++)
1656 : : {
1657 : 31 : GType type = param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
1658 : 31 : GType fundamental = G_TYPE_FUNDAMENTAL (type);
1659 : :
1660 [ + - ]: 31 : if ((param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0)
1661 : : {
1662 [ + + + - ]: 31 : if (fundamental == G_TYPE_STRING && storage[i]._gpointer != NULL)
1663 : 1 : g_free (storage[i]._gpointer);
1664 [ + + + - ]: 30 : else if (fundamental == G_TYPE_PARAM && storage[i]._gpointer != NULL)
1665 : 1 : g_param_spec_unref (storage[i]._gpointer);
1666 [ + + + - ]: 29 : else if (fundamental == G_TYPE_BOXED && storage[i]._gpointer != NULL)
1667 : 1 : g_boxed_free (type, storage[i]._gpointer);
1668 [ + + + - ]: 28 : else if (fundamental == G_TYPE_VARIANT && storage[i]._gpointer != NULL)
1669 : 1 : g_variant_unref (storage[i]._gpointer);
1670 : : }
1671 [ + + + - ]: 31 : if (fundamental == G_TYPE_OBJECT && storage[i]._gpointer != NULL)
1672 : 1 : g_object_unref (storage[i]._gpointer);
1673 : : }
1674 : :
1675 [ + + + - ]: 13 : if (return_value && G_VALUE_TYPE (return_value))
1676 : 10 : value_from_ffi_type (return_value, rvalue);
1677 : : }
|