LCOV - code coverage report
Current view: top level - glib/gobject - gclosure.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 483 611 79.1 %
Date: 2024-06-11 05:24:59 Functions: 31 34 91.2 %
Branches: 190 300 63.3 %

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

Generated by: LCOV version 1.14